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 instead of from anything you write in the page. Each URL segment becomes one crumb, so readers can see where they are and click back up a level.
Quick Start
Save a page anywhere under app/ and its trail appears on its own. A file at
app/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 roughly 120 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 apply before the words are joined. A two-digit sort prefix is
stripped, so 01-introduction shows as Introduction and keeps the sidebar
ordering out of the reader's way. And a word longer than two characters that
already mixes upper and lower case is passed through untouched, which is how a
segment like openAPI survives.
Home / Getting Started / IntroductionDeeper paths simply add 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 trail is also emitted 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.
One thing to know before you compare the two: 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 about 110 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 labelled aria-label="Breadcrumb"
so screen readers can jump to or skip it.