Navigation
Tabs, groups, and the two page shapes you author by hand.
navigation is the one required field that describes your site’s shape. It is a list of
tabs; each tab holds groups; each group holds pages.
{ "navigation": { "tabs": [ { "label": "Docs", "groups": [ { "label": "Get started", "pages": ["index", "quickstart"] }, { "label": "Authoring", "pages": ["authoring/pages", "authoring/navigation"] } ] } ] }}Every tab needs at least one group, and every group at least one page. An empty tab is a schema error, not an empty section — so a tab comes into existence at the moment it has real content to hold, not before.
Page references
Section titled “Page references”A bare string is a page id — and a page id is not quite the same thing as a file path. It is the identifier Reed derives from the file, and four rules shape it:
Every path segment is slugified independently
Lowercased, punctuation stripped.
Guide/Intro.mdxhas the page idguide/intro, notGuide/Intro.A nested index collapses to its directory
derived/index.mdxhas the page idderived. Write"derived", never"derived/index". A root-levelindex.mdxis the site root and is written"index".A frontmatter slug wins outright
A page whose frontmatter sets
slug: custom-routehas the page idcustom-route, whatever its path.Some files are not pages at all
A file whose name begins with
_, or one inside a dot-prefixed directory, is not loaded and therefore has no page id.
The written form is still constrained to ^[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*$ — which
permits uppercase, so "Guide/Intro" is a legal string that names no page.
reed check reports a page id that resolves to nothing, naming both what you wrote and
the id the file actually has. It is an error, so a navigation entry can never point at
nothing.
Nesting
Section titled “Nesting”A group entry can itself be a group object, nesting up to 5 levels:
{ "label": "Reference", "pages": [ { "label": "CLI", "pages": ["reference/cli/init", "reference/cli/build"] } ]}Generated API pages
Section titled “Generated API pages”An entry of the shape { "label": "...", "api": true, "spec": "ingestion" } generates a
complete set of endpoint pages from one OpenAPI spec. No MDX file exists for these —
Reed synthesizes them.
{ "label": "Ingestion API", "groups": [ { "label": "Ingestion API", "pages": [{ "label": "Ingestion API", "api": true, "spec": "ingestion" }] } ]}spec names a key declared under api.specs; you may omit it only when api.specs has
exactly one entry.
Two structural rules come with it: an API entry must be the only page in its group, and that group the only group in its tab. Reed requires a dedicated tab per spec — generated endpoint pages cannot be mixed alongside hand-written pages in one group.