Organize pages and API endpoints into topic folders
What you'll see
A site starts with a few pages and the author drops every .html and .hash file into a single folder: home.html, about.html, pricing.hash, product-a.hash, product-b.hash, support-faq.html, support-contact.html, and so on. As the site grows, this single folder accumulates dozens of files. Finding the right page means scrolling a long, flat list; the author starts encoding the section into the filename (support-faq, product-a) to claw back some grouping; and the URLs come out flat and meaningless — /support-faq, /product-a — with no shared section path to anchor them. The same thing happens to an app's endpoints: getOrders.js, createOrder.js, getUser.js and updateUser.js all land directly in #/API/, names start colliding (getList.js — list of what?), and an order_/user_ prefix becomes the manual workaround for the missing structure.
What's actually happening
A page's path on disk maps directly to its public URL. A hash file at #/Root/Products/Pricing.hash is served at /Products/Pricing, and an HTML file at /Support/Contact.html at /Support/Contact — the extension is dropped and spaces become hyphens. Crucially, this mapping includes the folders: subfolders are part of the URL, not just an organisational nicety for the file tree.
Pages live in one of two places, and the choice decides who can see the files. Put them under #/Root/ and the #/Root/ prefix is stripped from the URL while the files themselves stay inside the developer-only #/ tree, invisible to content editors. Put them in the workspace root instead and they are served from where they sit, but they also show up in the file tree for every user. Either layout gives the same URLs; only the visibility differs. What does not work is filing a page directly under #/, outside the well-known Root, API, Folder and Schemas folders — nothing there is served, and the page returns 404 at every URL.
This means folders are a first-class part of your site's URL and information architecture. Docly requires no routing configuration or manifest to make this work — creating the folder and putting the page in it is the entire setup. A folder that contains an Index.hash or Index.html is also served automatically at the folder's clean URL, so a topic folder gives you a natural section landing page at /products/ for free.
A single flat folder throws all of this away. Pages from unrelated sections sit side by side; the file list grows without grouping; section landing pages have nowhere to live; and authors resort to encoding the topic into the filename (support-faq.html, product-pricing.hash) to re-create, by hand and inconsistently, exactly the grouping folders give automatically. The resulting URLs (/support-faq) are flatter and less meaningful than the structured ones (/support/faq) the folder layout produces for free.
API endpoints follow the same rule
Every .js file in #/API/ is a server-side endpoint, and its path under #/API/ maps to its URL — recursively. #/API/hello.js is served at /API/hello, #/API/orders/create.js at /API/orders/create. No routing configuration is needed; creating the folder is the setup. A flat #/API/ loses this the same way a flat page folder does: unrelated endpoints side by side, and topic encoded into the filename (order_create.js) instead of the path (orders/create.js).
What to do
Pages
Organise pages into topic folders, one folder per section or subject area. Let the folder name carry the topic and the file name carry the specific page. Add an Index file to each folder for its section landing page. The result is readable, RESTful URLs and a file tree that scales.
Do — topic folders with Index landing pages:
#/Root/Products/Index.hash -> /Products/
#/Root/Products/Pricing.hash -> /Products/Pricing
#/Root/Products/Compare.hash -> /Products/Compare
#/Root/Support/Index.html -> /Support/
#/Root/Support/FAQ.html -> /Support/FAQ
#/Root/Support/Contact.html -> /Support/Contact
#/Root/About/Index.html -> /About/
#/Root/About/Team.html -> /About/TeamDon't — everything flat in one folder with prefixes:
#/Root/products-pricing.hash -> /products-pricing
#/Root/products-compare.hash -> /products-compare
#/Root/support-faq.html -> /support-faq
#/Root/support-contact.html -> /support-contact
#/Root/about.html -> /about
#/Root/about-team.html -> /about-team // which section?Don't — filed directly under #/, where nothing is served:
#/Products/Index.hash -> 404
#/Products/Pricing.hash -> 404The page content itself does not change — the same HTML or hash works regardless of which folder it lives in. Only the path, and therefore the URL, changes.
Link to pages by their clean, structured path, and link to a section by its folder with a trailing slash — never with a filename or extension:
<a href="/Products/">Products</a>
<a href="/Products/Pricing">Pricing</a>
<a href="/Support/FAQ">FAQ</a>These root-relative links are publish-safe: when a site is mounted under a subfolder, Docly rewrites leading-slash href and src attributes automatically. For URLs your JavaScript builds at runtime, use ~/ paths instead. See Use tilde paths in JavaScript and Omit file extensions in links.
A practical rule of thumb: as soon as two pages belong to the same subject, create a folder for them and give it an Index file. Reserve the site root for genuinely top-level pages (the home page in #/Root), and put everything section-specific in its own topic folder.
API endpoints
Group related endpoints into topic folders under #/API/, one folder per resource or feature area. Let the folder name carry the topic and the file name carry the action.
Do — topic folders, action filenames:
#/API/orders/list.js -> /API/orders/list
#/API/orders/create.js -> /API/orders/create
#/API/orders/cancel.js -> /API/orders/cancel
#/API/users/profile.js -> /API/users/profile
#/API/users/update.js -> /API/users/update
#/API/billing/invoice.js -> /API/billing/invoiceDon't — everything flat in the root with prefixes:
#/API/orderList.js -> /API/orderList
#/API/orderCreate.js -> /API/orderCreate
#/API/order_cancel.js -> /API/order_cancel
#/API/getUserProfile.js -> /API/getUserProfile
#/API/updateUser.js -> /API/updateUser
#/API/invoice.js -> /API/invoice // invoice for what?The endpoint code itself does not change — the same exported function works regardless of which folder it lives in:
// #/API/orders/create.js
export default (form) => {
if (!form.product) return { error: "Missing product" };
// ... create the order
return { ok: true };
}From the frontend, call the grouped endpoint exactly as you would a flat one — just include the folder in the path (and prefer ~/ so it survives publishing under a subfolder):
fetch('~/API/orders/create', {
method: 'POST',
body: new URLSearchParams({ product: 'SKU-42' })
});A practical rule of thumb: once you have more than a few endpoints, or as soon as two endpoints belong to the same resource, create a folder. Keep #/API/'s root reserved for genuinely cross-cutting, app-wide endpoints (for example a single #/API/health.js), and put everything feature-specific in its own topic folder.