Skip to content
sdocs

Routing

Every doc page has its own URL. The standalone CLI uses real paths (history routing); embedding defaults to #/ hash URLs. Both modes share the same route structure.

URL format

Routes are built from the doc's title: one slug per segment, with the section slug first when sections are declared. An entity can override its own (last) segment with slug="…" in its opener.

https://example.com/components/button
https://example.com/components/button/with-icon
https://example.com/guides/getting-started

Slugs

Each title segment is slugified the same way page headings are, in exactly these steps:

  1. lowercase the segment,
  2. strip everything that isn't a word character, whitespace, or -,
  3. trim, then replace runs of whitespace and _ with a single -.
TitleRoute
'Components / Button'/components/button
'Patterns / Login Form'/patterns/login-form
'@guides/Getting Started'/guides/getting-started
'Components / IconButton'/components/iconbutton

Important

CamelCase is not split. Only whitespace and underscores become hyphens, so IconButton slugifies to iconbutton, not icon-button. Either write the title with a space ('Icon Button') or set the segment explicitly with slug="icon-button" on the entity opener:

[SHOWCASE title="@components/IconButton" slug="icon-button"]

The slug value must be lowercase letters, digits, and hyphens — anything else is a build error. list_docs (see the MCP server) reports the resolved route for every entity, so you never have to guess.

Two entities that resolve to the same route are an error (shown full-page in dev; sdocs build fails) — give one a slug="…". URLs never silently renumber.

Sub-pages

Examples get a sub-segment:

EntryRoute
Button component (main page)/components/button
Button example WithIcon/components/button/with-icon

History mode (standalone CLI)

sdocs dev / sdocs run serve the app shell for any path and render client-side — a live SPA. sdocs build goes further: it prerenders every route into its own index.html — the sidebar, the prose, a per-route <title> (and the showcase description as the meta description) are real HTML in the file, and the app hydrates on load. Crawlers and no-JS readers get full pages; deep links work on any static host (GitHub Pages included) with no rewrite rules. Old #/… bookmarks from earlier sdocs versions are translated on load.

Hash mode (embedded)

When the Explorer is embedded in a host app, its routing defaults to #/components/button under whatever path the host mounts it on — no server cooperation needed. Override with the routing option or the routing prop if your host serves a fallback.

Deep linking

Any URL can be bookmarked, shared, or linked to. (Folders keep their default expand state — deep-linking doesn't auto-expand the path to the entry.)

When a component doc has several [COMPONENT] blocks, the selected tab is tracked in the URL as ?tab=<preview-slug> — so a specific preview is shareable (/components/navtree?tab=navtree-item). The first tab is the default and keeps the URL clean; switching entity drops the parameter.

Home and About

The root route shows the entity the config's home path points at, otherwise the built-in About page (project logo, doc counts, and the sdocs version). About is always reachable at /about, and the changelog of the sdocs that built the site at /changelog — both are in the menu at the right of the top bar, beside the theme toggle and fullscreen. Neither route can be claimed by an entity; a title that would land on one is a build error rather than a page that silently never appears.

An address that matches no entity gets a not-found page naming it, with a way back into each section. On a static build it carries a real 404 status.

The logo/title always links to the root. An entity marked hide keeps its route but never appears in a sidebar — useful for link-only pages.

Fullscreen mode

Clicking the fullscreen button hides the top bar and the sidebar — only the content remains. To leave, move the pointer into the top-left corner (an Exit fullscreen button appears) or press Esc. This is a UI state only — it doesn't affect the URL, and it isn't persisted.

See also