Fern Navigation & Site Structure
Fern documentation is configured at two levels: site-level in docs.yml (and, for multi-product
or multi-version sites, in per-product / per-version .yml files), and page-level in each .md /
.mdx file's frontmatter. This skill catalogs the whole site-structure surface — what each building
block does, when to reach for it, and the exact YAML — and points to
references/navigation-reference.md for every field, default,
and copy-paste example.
This skill is structure & configuration knowledge. In-page MDX components (<Card>, <Steps>,
<Tabs> content tabs, <Accordion>, callouts…) belong to the fern-components skill. Page
placement conventions, the style guide, SPDX headers, terminology, and this repo's .md-vs-.mdx
rule belong to the dynamo-docs skill. Use all three together when authoring.
"tabs" and "tabs" are two different things (read this first)
Fern overloads several words. Keep the layers straight before touching config:
| Term |
Layer |
Where it lives |
Owned by |
<Tabs> / <Tab> |
in-page content tabs |
inside a .mdx body |
fern-components |
tabs: navigation |
site-level nav tabs |
docs.yml top-level + navigation: |
this skill |
<Versions> component |
in-page version-conditional content |
inside a .mdx body |
fern-components |
versions: config |
site-wide version switcher |
docs.yml + versions/*.yml |
this skill |
The mental model: how a URL is built
Fern composes each page's URL by concatenating a slug from every level of the hierarchy it passes
through, outermost first:
/<product>/<version>/<tab>/<section>/<folder>/<page>
Each level auto-generates a slug from its display name (or filename, for folders). Any level can
slug: rename itself, skip-slug: true drop itself from the path, or a page's frontmatter slug:
override the whole section/folder portion (product/version prefix is preserved). Understanding this
composition is the key to predicting and controlling URLs — see the reference's Slugs section.
Choosing the right structural tool
Decide by how different two bodies of content are, from lightest to heaviest:
| You want to… |
Reach for |
Notes |
| Order pages in the sidebar |
sections / pages / folders |
The default. Folders auto-discover files. |
| Auto-build nav from a directory tree |
folder: |
index.md(x) becomes the section overview; subdirs nest. |
| Group whole content areas (Guides vs API Ref) |
tabs |
Top-level tabs:, referenced in navigation:. |
| Same area, different audience/perspective (REST vs GraphQL, dev vs PM) |
tab variants |
variants: instead of layout:; supports RBAC. |
| Multiple releases of the same docs |
versions |
Dropdown switcher; versions/*.yml. Team plan. |
| Multiple distinct products under one site |
products |
Product switcher; products/*.yml. Team plan. Can nest versions. |
| A dated log of changes |
changelog |
A changelog/ folder, surfaced as a tab or a section. |
| A root page before any product |
landing-page: |
Independent of products/versions. |
| Link out (GitHub, dashboard) from nav |
href tab / external product / navbar link |
No internal content. |
Rules of thumb:
- Don't reach for products when a tab will do. Products are a heavyweight, Team/Enterprise
feature that removes top-level
navigation/tabs and splits config into files. Use them only for
genuinely separate products, not for two sections of one product.
- Variants vs tabs: variants = different lenses on the same area; tabs = different areas.
- Versions and products compose — a product can be versioned, and versioned/unversioned products
coexist. Standalone versioning (no products) is simpler; prefer it if you have one product.
Hard constraints that bite (verify against these)
- Products/versions eject top-level nav. When you add
products: (or versions:), you MUST
remove the top-level navigation: and tabs: from docs.yml — they move into the per-product /
per-version files. fern check rejects a navigation block coexisting with products: and would
otherwise render an empty site.
- External products /
href tabs cannot have navigation, tabs, layout, or variants.
- A tab needs exactly one of
layout, variants, or href — never href + content.
- The default version (first in the list) can't be
hidden.
changelog/ must be named exactly that, files live flat in its root (no subdirs), and file
names must be dated (YYYY-MM-DD, MM-DD-YYYY, or MM-DD-YY). Section-level changelogs can't nest
under an api entry.
- Team plan gate: versions and products are Team/Enterprise features.
The eight source pages (what's in the reference)
references/navigation-reference.md mirrors the eight pages of
Fern's navigation/ docs section, with full YAML and every field:
- Overview — the two config levels; index of the structural cards.
- Sections, pages, folders — the
navigation: tree, nesting, folder auto-discovery, slugs,
hiding, availability badges, collapsed state, sidebar icons, external links.
- Tabs & tab variants —
tabs: + navigation:, all tab props, variants, placement/style.
- Versions —
versions/*.yml, the switcher, availability, slugs, audiences, hiding, styling.
- Products —
products/*.yml, internal vs external, the switcher, versioned products, landing
page, audiences, conditional content, search scoping, selector CSS.
- Changelogs —
changelog/ folder, tab vs section placement, entry files, tags, layouts, RSS.
- Frontmatter (page-level settings) — every per-page field: titles, slug, description, layout,
TOC/nav/feedback toggles, availability, SEO/OpenGraph, changelog tags.
- Site-level settings — the full
docs.yml surface: colors, logo, typography, layout, theme,
navbar/footer links, instances, settings (search etc.), page actions, redirects, metadata,
analytics, edit-this-page, Ask Fern, agents/llms.txt, check rules.
Workflow for a structure change in this repo
- Locate the config. Find this repo's
docs.yml (and any products/ or versions/ files) —
dynamo-docs owns where pages live; this skill owns their arrangement.
- Pick the lightest tool from the table above that expresses the change.
- Write the YAML from the reference, honoring the hard constraints.
- Mind the URL impact. Any slug/section/tab/version/product change alters URLs — add
redirects: for moved pages, and remember check.rules.missing-redirects.
- Validate: run
fern check (broken links, missing redirects, config coherence) before publish.
Keeping this skill current
Fern's config schema drifts. The source of truth is fern-api/docs (branch main),
fern/products/docs/pages/navigation/*.mdx. manifest.json records each tracked page's git blob
SHA as of the last sync. To check for drift and refresh:
python3 scripts/refresh_navigation.py --check # what changed upstream?
python3 scripts/refresh_navigation.py --fetch --out /tmp/fern # download changed pages
# ...update references/navigation-reference.md + this SKILL.md from those...
python3 scripts/refresh_navigation.py --sync # record new SHAs as current
For anything load-bearing, verify field names against the live
docs-yml schema or the current docs rather than
trusting a summary — this surface changes.
1---2name: fern-navigation3description: Knowledge of Fern's site-level navigation and structure configuration — how a docs site is organized in `docs.yml` (and product/version `.yml` files) using sections, pages, folders, tabs, tab variants, versions, products, changelogs, and site-level settings, plus per-page frontmatter. Use when designing or changing the shape of a Fern docs site (adding a tab, splitting into products, cutting a version, restructuring the sidebar, moving the changelog, tuning the navbar/layout/theme) or when a user asks "what options does Fern give me for navigation" or "how do I configure X in docs.yml". Complements fern-components (in-page MDX components) and dynamo-docs (this repo's page placement, style guide, and .md/.mdx rules).4license: Apache-2.05---67# Fern Navigation & Site Structure89<!--10SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.11SPDX-License-Identifier: CC-BY-4.012-->1314Fern documentation is configured at two levels: **site-level** in `docs.yml` (and, for multi-product15or multi-version sites, in per-product / per-version `.yml` files), and **page-level** in each `.md` /16`.mdx` file's frontmatter. This skill catalogs the whole site-structure surface — what each building17block does, **when to reach for it**, and the exact YAML — and points to18[`references/navigation-reference.md`](references/navigation-reference.md) for every field, default,19and copy-paste example.2021This skill is **structure & configuration knowledge**. In-page MDX components (`<Card>`, `<Steps>`,22`<Tabs>` content tabs, `<Accordion>`, callouts…) belong to the **fern-components** skill. Page23placement conventions, the style guide, SPDX headers, terminology, and this repo's `.md`-vs-`.mdx`24rule belong to the **dynamo-docs** skill. Use all three together when authoring.2526## "tabs" and "tabs" are two different things (read this first)2728Fern overloads several words. Keep the layers straight before touching config:2930| Term | Layer | Where it lives | Owned by |31|---|---|---|---|32| **`<Tabs>` / `<Tab>`** | in-page content tabs | inside a `.mdx` body | fern-components |33| **`tabs:` navigation** | site-level nav tabs | `docs.yml` top-level + `navigation:` | **this skill** |34| **`<Versions>` component** | in-page version-conditional content | inside a `.mdx` body | fern-components |35| **`versions:` config** | site-wide version switcher | `docs.yml` + `versions/*.yml` | **this skill** |3637## The mental model: how a URL is built3839Fern composes each page's URL by concatenating a slug from **every level** of the hierarchy it passes40through, outermost first:4142```43/<product>/<version>/<tab>/<section>/<folder>/<page>44```4546Each level auto-generates a slug from its display name (or filename, for folders). Any level can47`slug:` rename itself, `skip-slug: true` drop itself from the path, or a page's frontmatter `slug:`48override the whole section/folder portion (product/version prefix is preserved). Understanding this49composition is the key to predicting and controlling URLs — see the reference's Slugs section.5051## Choosing the right structural tool5253Decide by **how different two bodies of content are**, from lightest to heaviest:5455| You want to… | Reach for | Notes |56|---|---|---|57| Order pages in the sidebar | **sections / pages / folders** | The default. Folders auto-discover files. |58| Auto-build nav from a directory tree | **`folder:`** | `index.md(x)` becomes the section overview; subdirs nest. |59| Group whole content areas (Guides vs API Ref) | **tabs** | Top-level `tabs:`, referenced in `navigation:`. |60| Same area, different audience/perspective (REST vs GraphQL, dev vs PM) | **tab variants** | `variants:` instead of `layout:`; supports RBAC. |61| Multiple releases of the same docs | **versions** | Dropdown switcher; `versions/*.yml`. Team plan. |62| Multiple distinct products under one site | **products** | Product switcher; `products/*.yml`. Team plan. Can nest versions. |63| A dated log of changes | **changelog** | A `changelog/` folder, surfaced as a tab or a section. |64| A root page before any product | **`landing-page:`** | Independent of products/versions. |65| Link out (GitHub, dashboard) from nav | **`href` tab / external product / navbar link** | No internal content. |6667Rules of thumb:68- **Don't reach for products when a tab will do.** Products are a heavyweight, Team/Enterprise69 feature that removes top-level `navigation`/`tabs` and splits config into files. Use them only for70 genuinely separate products, not for two sections of one product.71- **Variants vs tabs:** variants = different *lenses on the same area*; tabs = *different areas*.72- **Versions and products compose** — a product can be versioned, and versioned/unversioned products73 coexist. Standalone versioning (no products) is simpler; prefer it if you have one product.7475## Hard constraints that bite (verify against these)7677- **Products/versions eject top-level nav.** When you add `products:` (or `versions:`), you MUST78 remove the top-level `navigation:` and `tabs:` from `docs.yml` — they move into the per-product /79 per-version files. `fern check` rejects a `navigation` block coexisting with `products:` and would80 otherwise render an empty site.81- **External products / `href` tabs** cannot have `navigation`, `tabs`, `layout`, or `variants`.82- **A tab needs exactly one of** `layout`, `variants`, or `href` — never `href` + content.83- **The default version (first in the list) can't be `hidden`.**84- **`changelog/` must be named exactly that**, files live flat in its root (no subdirs), and file85 names must be dated (`YYYY-MM-DD`, `MM-DD-YYYY`, or `MM-DD-YY`). Section-level changelogs can't nest86 under an `api` entry.87- **Team plan gate:** versions and products are Team/Enterprise features.8889## The eight source pages (what's in the reference)9091[`references/navigation-reference.md`](references/navigation-reference.md) mirrors the eight pages of92Fern's `navigation/` docs section, with full YAML and every field:93941. **Overview** — the two config levels; index of the structural cards.952. **Sections, pages, folders** — the `navigation:` tree, nesting, folder auto-discovery, slugs,96 hiding, availability badges, collapsed state, sidebar icons, external links.973. **Tabs & tab variants** — `tabs:` + `navigation:`, all tab props, variants, placement/style.984. **Versions** — `versions/*.yml`, the switcher, availability, slugs, audiences, hiding, styling.995. **Products** — `products/*.yml`, internal vs external, the switcher, versioned products, landing100 page, audiences, conditional content, search scoping, selector CSS.1016. **Changelogs** — `changelog/` folder, tab vs section placement, entry files, tags, layouts, RSS.1027. **Frontmatter (page-level settings)** — every per-page field: titles, slug, description, layout,103 TOC/nav/feedback toggles, availability, SEO/OpenGraph, changelog tags.1048. **Site-level settings** — the full `docs.yml` surface: colors, logo, typography, layout, theme,105 navbar/footer links, instances, settings (search etc.), page actions, redirects, metadata,106 analytics, edit-this-page, Ask Fern, agents/llms.txt, check rules.107108## Workflow for a structure change in this repo1091101. **Locate the config.** Find this repo's `docs.yml` (and any `products/` or `versions/` files) —111 `dynamo-docs` owns where pages live; this skill owns their arrangement.1122. **Pick the lightest tool** from the table above that expresses the change.1133. **Write the YAML** from the reference, honoring the hard constraints.1144. **Mind the URL impact.** Any slug/section/tab/version/product change alters URLs — add115 `redirects:` for moved pages, and remember `check.rules.missing-redirects`.1165. **Validate:** run `fern check` (broken links, missing redirects, config coherence) before publish.117118## Keeping this skill current119120Fern's config schema drifts. The source of truth is `fern-api/docs` (branch `main`),121`fern/products/docs/pages/navigation/*.mdx`. `manifest.json` records each tracked page's git blob122SHA as of the last sync. To check for drift and refresh:123124```bash125python3 scripts/refresh_navigation.py --check # what changed upstream?126python3 scripts/refresh_navigation.py --fetch --out /tmp/fern # download changed pages127# ...update references/navigation-reference.md + this SKILL.md from those...128python3 scripts/refresh_navigation.py --sync # record new SHAs as current129```130131For anything load-bearing, verify field names against the live132[`docs-yml` schema](https://schema.buildwithfern.dev/docs-yml.json) or the current docs rather than133trusting a summary — this surface changes.