One crumb per path segment, read from usePathname(). Nothing in the page
file changes them.
Breadcrumbs
Breadcrumbs sit above every page in the doc layout, built from the current route rather than from anything in the page file. Each URL segment becomes one crumb, so readers can see where they are and click back up a level. What follows covers the label rules, the structured-data copy of the trail, and the edge cases.
Quick Start
Save a page anywhere under content/ and its trail appears on its own. A file
at content/features/api/api-blocks.mdx serves /features/api/api-blocks,
which splits into three crumbs behind a house icon that links to the site root.
Home / Features / API / API BlocksLabels come from formatSegmentLabel() in lib/format-segment.ts. It splits
the segment on hyphens, formats each word, and joins the words with spaces. The
same helper names the sidebar entries, so a page reads the same in both places.
Adding Options
Casing is not a plain capitalize. formatSegmentLabel() checks every word
against a list of 121 acronyms and product names, and a match renders in its
canonical form: API, JWT, FAQ, MCP, SQL, OAuth, GraphQL, SaaS,
TypeScript, MongoDB. Everything else gets an initial capital and a
lowercased tail.
/faq -> Home / FAQ
/api-reference/pet -> Home / API Reference / Pet
/features/platform/mcp-server
-> Home / Features / Platform / MCP ServerTwo more rules run before the words are joined. The formatter strips a two-digit
sort prefix, so 01-introduction shows as Introduction and keeps the sidebar
ordering out of the reader's way. It also passes a word straight through when
that word runs longer than two characters and already mixes upper and lower
case, which is how a segment like openAPI survives.
Home / Getting Started / IntroductionDeeper paths add more crumbs. On /features/platform/table-of-contents, the
first three crumbs link to their own routes and the last renders as plain text
carrying aria-current="page".
Home / Features / Platform / Table Of ContentsAdvanced
The renderer also emits the trail as BreadcrumbList JSON-LD next to the
article, so search engines index the hierarchy. Home takes position 1 and each
route segment follows in order.
The two labels do not always match. The JSON-LD builder in
app/[[...slug]]/page.tsx runs its own simple capitalizer rather than
formatSegmentLabel(): it uppercases the first letter of each hyphen-separated
word and leaves the rest alone, so api-blocks becomes Api Blocks in the
structured data while the rendered crumb reads API Blocks. It also keeps a
two-digit sort prefix that the visible label drops.
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://docs.example.com"
},
{
"@type": "ListItem",
"position": 2,
"name": "Features",
"item": "https://docs.example.com/features"
},
{
"@type": "ListItem",
"position": 3,
"name": "Platform",
"item": "https://docs.example.com/features/platform"
},
{
"@type": "ListItem",
"position": 4,
"name": "Breadcrumbs",
"item": "https://docs.example.com/features/platform/breadcrumbs"
}
]
}Three edge cases round out the behavior. The site root renders no breadcrumb at
all, because the component returns null for /. An archived version route
carries its version segment as the first crumb, so /v1/getting-started reads
Home / V1 / Getting Started. And an index.mdx page shows its directory as
the last crumb, since the route stops at the directory name.
To teach the formatter a new acronym, add the word in its canonical casing to
PRESERVE_UPPERCASE in lib/format-segment.ts. Matching is case-insensitive,
so one entry covers every spelling that appears in a URL.
Options
route segmentsstring[]Default: current routeacronym casinglookupDefault: PRESERVE_UPPERCASEA word matching the list renders in its canonical casing: API, JWT, FAQ,
MCP, OAuth, GraphQL, SaaS, MongoDB, and 113 more. Comparison ignores
case.
mixed-case wordsstringDefault: passed throughA word over two characters that already mixes upper and lower case keeps its original spelling instead of being re-capitalized.
plain wordsstringDefault: CapitalizedAnything else gets an initial capital and a lowercased tail, with hyphens rendered as spaces.
numeric prefixstringDefault: strippedA leading two-digit sort prefix such as 01- is removed from the label.
home crumblinkDefault: /A house icon at the head of the trail, always linking to the site root.
current crumbbooleanDefault: trueThe last crumb renders as text with aria-current="page" rather than a link.
landmarkstringDefault: BreadcrumbThe trail is an ordered list inside a nav labeled aria-label="Breadcrumb"
so screen readers can jump to or skip it.