v1.0.0 — zero config needed

Breadcrumbs that
write themselves

Define your routes once. Get auto-generated breadcrumbs everywhere — with async labels, SEO JSON-LD injection, and adapters for every major React router.

Get started → View on GitHub
myapp.com/products/123/reviews
Auto-generated breadcrumb — click a path below
npm install breadcrumb-core
The problem
Stop writing breadcrumbs
on every page

Route changes silently break them. Dynamic labels get duplicated. Nobody wins.

products/[id]/reviews.tsx Before
// Written by hand on every page 😩
<Breadcrumb>
  <Item>Home</Item>
  <Item>Products</Item>
  <Item>
    {'{ /* fetch name yourself */}'}
    {product.name}
  </Item>
  <Item>Reviews</Item>
</Breadcrumb>

// Repeat on 40 other pages...
// Route changes = silent breakage 💀
routes.ts + any page After
// Define once ✅
export const routes = [
  { path: "/", label: "Home" },
  { path: "/products", label: "Products" },
  {
    path: "/products/:id",
    label: async ({ params }) =>
      getProductName(params.id)
  },
  { path: "/products/:id/reviews",
    label: "Reviews" },
]

// Any page — zero code needed
<AutoBreadcrumb />
// → Home / Products / iPhone 15 / Reviews
How it works
4 steps. Zero config.

The library reads your route definitions once and handles everything automatically.

1

Parse URL

/products/123/reviews becomes four typed ancestor segments

2

Match routes

Each segment matched against your config with named param extraction

3

Resolve labels

Strings used directly. Async functions awaited and cached for instant back-nav

4

Render

Your <AutoBreadcrumb> renders. Skeleton shown while async resolves

Features
Everything you needed
but couldn't find

The combination no existing solution provides.

Async labels with cache

Labels can be async functions. Results are cached by path + params so back-navigation is instant. Pass renderSkeleton for a loading state.

🔍

Schema.org JSON-LD

One prop enables automatic BreadcrumbList structured data injection for Google rich results. No extra libraries.

🙈

Hidden segments

Mark layout-only routes with hidden: true and they're skipped in the breadcrumb without affecting your routing at all.

📄

Document title sync

Set syncDocumentTitle and the browser tab updates to iPhone 15 — Products — MyApp automatically on every navigation.

🎨

Headless hook

Use useBreadcrumb() to get raw items and build fully custom renders with your own design system. Zero opinions on markup.

🗜️

Smart collapsing

Set maxItems={4} and deep paths collapse in the middle with automatically. No extra logic needed.

Adapters
Works with your router

Each adapter reads pathname automatically. Same API, every framework.

react-router v6+
import { AutoBreadcrumb }
from 'breadcrumb-core/react-router'
next.js app router
import { AutoBreadcrumb }
from 'breadcrumb-core/next'
tanstack router v1
import { AutoBreadcrumb }
from 'breadcrumb-core/tanstack-router'
headless any
import { useBreadcrumb }
from 'breadcrumb-core/headless'
Comparison
Why existing tools fall short

2M+ combined weekly npm installs — none covering all the cases.

Tool Async labels SEO JSON-LD Multi-router Headless hook Cache
breadcrumb-core ✦
use-react-router-breadcrumbs
antd Breadcrumb
Manual per-page
API reference
Simple. Composable. Typed.

Full TypeScript support. Every prop documented.

<AutoBreadcrumb />

PropDefaultDescription
separator"/"Between items
maxItemsCollapse middle with …
showHometrueInclude root item
injectJsonLdfalseSchema.org JSON-LD
syncDocumentTitlefalseAuto document.title
appNameAppended to synced title
renderItemCustom item renderer fn
renderSkeletonLoading placeholder

RouteConfig interface

interface RouteConfig {
  path:   string
  label:
    | string
    | (({ params }) =>
        string | Promise<string>)
  icon?:   ReactNode
  hidden?: boolean
}

// useBreadcrumb() returns:
interface BreadcrumbItem {
  path:     string
  label:    string
  params:   RouteParams
  isLast:   boolean
  icon?:    ReactNode
}

Ship better breadcrumbs
in 5 minutes

One install. One provider. Zero breadcrumb code per page. Ever.

Read the docs → View on GitHub