Before you begin
- At least one page file ready to link, see Write if you still need to create content
- Preview running locally when you want to confirm sidebar changes as you edit
Define your site's navigation explicitly in the sidebar property of docs.json. By default, sidebar is a flat array of groups for a single-language site. For multi-locale sites, replace that array with an object keyed by locale code (for example en, fr) — each key holds its own navigation tree, and docs.page loads the tree that matches the locale segment in the URL:
{
"sidebar": [
{
"group": "Getting Started",
"pages": [
{ "title": "Introduction", "href": "/" }
]
}
]
}{
"sidebar": {
"en": [
{
"group": "Getting Started",
"pages": [
{ "title": "Introduction", "href": "/" }
]
}
],
"fr": [
{
"group": "Commencer",
"pages": [
{ "title": "Introduction", "href": "/" }
]
}
]
}
}In a multi-locale setup, locale keys match URL segments and docs/{locale}/ folders; each key holds its own tree with locale-neutral href values. See Locales for default, link prefixing, and the full workflow. For field reference, see Sidebar.
Group related pages together
Pick a group inside the sidebar array (or inside a locale key when using multi-locale). Each group is an object with a
pagesarray and optionalgrouplabel,icon, landinghref, andtabassignment:json{ "group": "Authoring", "icon": "pen-to-square", "pages": [ { "title": "Write", "href": "/authoring/write" }, { "title": "Organize", "href": "/authoring/organize" } ] }Add a page link to the sidebar
Add a leaf entry for your new page. Set
titleto the label readers see in the sidebar (keep it short, two to four words). Sethrefto the page's public URL path:json{ "title": "Preview", "href": "/authoring/preview" }The path must match the file under
docs/without the extension. For example,docs/authoring/preview.mdxmaps to/authoring/preview.Scale up with nested sections
When a group grows, replace a leaf entry with a nested group (same shape, with its own
pagesarray):json{ "group": "Manage", "pages": [ { "title": "Redirects", "href": "/authoring/redirects" }, { "title": "Locales", "href": "/authoring/locales" } ] }Nested groups can stack several levels deep. When the active page matches a nested group's
hrefor any link inside it, that section stays expanded.Match sidebar order to reading flow
Array order is sidebar order top to bottom. It also drives default previous/next links unless a page overrides them with
previousandnextin page frontmatter.
Groups without a group label still render, as an unlabeled block of links. External URLs in href are supported and show an external-link indicator.
For every sidebar field and type, see docs.json.
{
"tabs": [
{ "id": "docs", "title": "Documentation", "href": "/" },
{ "id": "features", "title": "Features", "href": "/features" }
]
}Use site tabs when major areas (guides, features, reference) need separate sidebar slices.
Show the right sidebar on each tab
Tag sidebar groups with the
tabfield set to a tabid:json{ "group": "Getting Started", "tab": "docs", "pages": [{ "title": "Introduction", "href": "/" }] }Share a section across every tab
Leave
taboff when a section should appear regardless of active tab, for example a global About group.
While a tab is active, docs.page shows groups tagged for that tab plus any untagged groups. The active tab is derived from the current URL, longest matching tab href wins.
Site tabs split the header and sidebar. They are not the same as the <Tabs> MDX component, which switches panels inside a single page.
Pin GitHub, Discord, or app links above the sidebar (outside the main tree) with the top-level anchors array in docs.json. Each entry needs title, href, and optional icon:
{
"anchors": [
{
"icon": "github",
"title": "GitHub",
"href": "https://github.com/acme/handbook"
},
{
"icon": "message",
"title": "Discord",
"href": "https://discord.gg/acme"
}
]
}See Links for icon names and locale or tab scoping.
After you edit docs.json:
- See changes as you edit: reload Preview and open the page you added
- Confirm the link landed in the right place: check the new entry appears in the expected group and position
- Check nested groups expand correctly: click through nested groups; the section containing the active page should stay expanded
- Confirm each tab shows the right tree: switch between tab labels in the header and verify each tab's groups
- Catch broken hrefs before push: run
docs checkfor internal link and href mismatches
| Symptom | Likely cause | Fix |
|---|---|---|
| Page does not appear in the sidebar | No entry in docs.json sidebar | Add a leaf { "title", "href" } object to the correct group's pages array |
| Sidebar link returns 404 | href does not match the file path under docs/ | Align href with the URL path (no extension). Example: docs/api/auth.mdx → /api/auth |
| Page shows under the wrong tab | Group tab does not match the tab you expect | Set tab to the correct tab id, or omit tab to show the group on every tab |
| Nested section stays collapsed | Active page is not under that group's href or nested links | Open a page inside the nested group, or set the group's href to its section landing page |
| Previous/next order feels wrong | Sidebar array order differs from the reading flow you want | Reorder entries in the group's pages array, or set previous / next in page frontmatter |
| Shortcut missing above the sidebar | Repository or community links use anchors, not sidebar groups | Add entries under anchors in docs.json. See Links |
- Write: Create page files and frontmatter before you add them to the sidebar.
- Preview: Reload locally to confirm sidebar groups, tabs, and link order.
- Sidebar: How groups, nested pages, and locale keys form the navigation tree.
- Tabs: Split large sites into header tabs and scope sidebar groups per tab.
- Links: Add GitHub, community, or app shortcuts above the sidebar with anchors.
- docs.json: Field lookup for
sidebar,tabs,anchors, and every other config key.
