Navigation Configuration
Build clear tabbed navigation, nested groups, anchors, versions, and language selectors in docs.json.
Mental model
HolyDocs navigation has three layers:
tabsdivide the site into large product surfaces.groupsorganize the sidebar inside a tab.- Nested groups let you fan out big sections like components, APIs, or SDKs without flattening everything into one wall.
If a reader has to scroll the sidebar to discover the product surface they need, your tabs are too broad or your groups are too flat.
Flat groups
Use flat groups for small sites:
json{ "navigation": { "groups": [ { "group": "Getting Started", "pages": ["introduction", "quickstart", "installation"] }, { "group": "Guides", "pages": ["guides/cicd", "guides/seo"] } ] }}
Each page string maps to a file path relative to your docs root, without the .mdx extension.
Tabs for large sites
For bigger docs sites, use tabs to separate workflows:
json{ "navigation": { "tabs": [ { "tab": "Documentation", "icon": "book-open", "groups": [ { "group": "Getting Started", "pages": ["introduction", "quickstart"] }, { "group": "Configuration", "pages": ["global-settings", "navigation-config"] } ] }, { "tab": "API Reference", "icon": "code-xml", "groups": [ { "group": "Overview", "pages": ["api", "api/authentication"] } ] } ] }}
Tab design rules
- One tab should represent one reader job, not one internal team.
- Keep tab count tight. Four to six tabs is usually enough.
- Put the highest-frequency workflow first.
Landing pages for tabs
By default, clicking a tab takes the reader to the first leaf page in that tab's groups. If returning visitors have already been into the tab, their last-visited page within it is restored from localStorage instead.
Set landing on a tab to override both behaviors and pin the click target to a curated entry page — an overview, a feature tour, or a marketing-style hero:
json{ "navigation": { "tabs": [ { "tab": "Build", "landing": "build/overview", "groups": [ { "group": "Workflow primitives", "pages": ["build/overview", "build/triggers", "build/actions"] } ] } ] }}
Use landing when the first leaf in your tree isn't the page you want readers to see first. Skip it when the natural first page already serves that purpose.
Nested groups
Nested groups are the main tool for granular docs without nav sprawl:
json{ "group": "Components", "pages": [ "components", { "group": "Structure & Layout", "pages": [ "components/tabs", "components/code-group", "components/steps" ] }, { "group": "Attention & Notices", "pages": [ "components/callout", "components/banner", "components/badge" ] } ]}
This pattern is how you turn one monolithic page into a browsable section without inflating the top-level sidebar.
Icons
You can add icons to tabs, groups, and anchors:
json{ "navigation": { "tabs": [ { "tab": "CLI", "icon": "terminal", "groups": [ { "group": "Local Workflow", "icon": "wrench", "pages": ["cli/dev", "cli/build", "cli/check"] } ] } ] }}
Use icons sparingly. They should help scanning, not decorate every row.
Anchors
Anchors pin durable external links into the sidebar:
json{ "navigation": { "anchors": [ { "name": "Dashboard", "url": "https://app.example.com", "icon": "layout-dashboard" }, { "name": "GitHub", "url": "https://github.com/example/docs", "icon": "github" } ] }}
Good anchor candidates:
- App dashboard
- GitHub repo
- Status page
- Support portal
Versions
Use the built-in version selector when readers need multiple supported releases:
json{ "navigation": { "versions": [ { "name": "v3", "url": "/v3", "default": true, "lifecycle": "active" }, { "name": "v2", "url": "/v2", "lifecycle": "maintenance" }, { "name": "v1", "url": "/v1", "lifecycle": "deprecated", "sunsetDate": "2026-12-31", "migrationUrl": "https://docs.example.com/guides/migrate-v3" } ] }}
Hide versions only when you must keep them reachable by direct URL but no longer want them in the primary selector.
Languages
Language selectors live in the same navigation block:
json{ "navigation": { "languages": [ { "code": "en", "name": "English", "url": "/" }, { "code": "es", "name": "Español", "url": "/es" }, { "code": "ja", "name": "Japanese", "url": "/ja" } ] }}
Pair this with the broader Internationalization settings when you are managing translated builds.
OpenAPI-driven groups
You can attach an OpenAPI source directly to a navigation group so HolyDocs generates endpoint pages into a dedicated directory:
json{ "group": "REST API", "openapi": { "source": "https://api.example.com/openapi.json", "directory": "api/reference" }, "pages": []}
This works best when you keep human-written overview pages next to generated endpoint pages rather than mixing everything in one directory.
Common mistakes
Tabs are for major reader journeys. If you are making one tab per feature team, collapse them into groups instead.
Large sections should start with a landing page before the long tail of nested detail pages.
Avoid nav structures like Guides / Concepts / APIs / Components / Enterprise when your real reader jobs are Setup / Customize / Integrate / Operate.