Skip to content

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Repository files navigation

NextCrumbs

MUI ^7 breadcrumbs for any React app. Works with Vite, CRA, Remix, and plain React. Next.js is optional (the package was originally built for it). Pass your own LinkComponent when you want client-side routing. Optional URL helpers and SEO JSON-LD. Zero runtime dependencies (peers only).

Item Value Badge
Version 0.2.1 (do not use 0.2.0) npm
GitHub repo github.com/ameshkin/nextcrumbs
CI .github/workflows/ci.yml CI - main CI - dev
npm package @ameshkin/nextcrumbs npm
Install npm i @ameshkin/nextcrumbs install test
Peer deps @mui/material@^7, @mui/icons-material@^7, @emotion/*@^11, react@>=18, react-dom@>=18
(Optional: react-router-dom@>=6)
peer deps
Types TypeScript types
License MIT license
Bundle size bundlephobia bundle size
Deps status libraries.io deps

0.2.0 is broken. Its exports pointed at ./public/* while the tarball only ships dist/. Use 0.2.1+. Details: docs/changes.md.


Menu


Features

  • Works without Next.js. Vite, CRA, Remix, and plain React are first-class. Next.js is optional.
  • MUI ^7 breadcrumbs under the hood (accessible, stable)
  • Pluggable LinkComponent. Use MUI's default link, React Router Link (linkProp="to"), or next/link
  • Optional URL → items helpers: usePathBreadcrumbs (client) and RSC-safe buildPathBreadcrumbs
  • React Router helper on a subpath only (useReactRouterBreadcrumbs)
  • JSON-LD helpers for schema.org BreadcrumbList (no example.com default)
  • First-class maxItems / collapse, size, truncate, and optional jsonLdOrigin
  • Tree-shakable subpath exports (/breadcrumbs, /hooks/*, /utils/*)
  • Fully typed with TypeScript
  • Trusted Publishing workflow (.github/workflows/publish.yml) for OTP-free CI releases

Originally built for Next.js App Router. The public API is router-agnostic, so the bundler does not matter.


Requirements

  • Node 20.19+ (or 22.12+) for developing / CI
  • React 18+ (React 19 supported in tests)
  • @mui/material ^7 (MUI 8/9 are outside this peer range)
  • @mui/icons-material ^7 (default home / separator icons)
  • @emotion/react and @emotion/styled ^11
  • Next.js is not required. Use it only if your app already does (App Router examples assume 13.4+)
  • (Optional) react-router-dom 6+ only if you import the React Router subpath (common with Vite)

Install

npm i @ameshkin/nextcrumbs

# required peers
npm i @mui/material @mui/icons-material @emotion/react @emotion/styled react react-dom

# optional: only if you use the React Router subpath hook (typical Vite SPA)
npm i react-router-dom

You do not need Next.js. Vite and other React toolchains only need the peers above (plus React Router if you use that subpath).


Quick Start (Vite / any React)

No Next.js. Default MUI links work out of the box:

import { Breadcrumbs } from "@ameshkin/nextcrumbs";

export function HeaderTrail() {
  return (
    <Breadcrumbs
      items={[
        { label: "Home", href: "/" },
        { label: "Products", href: "/products" },
        { label: "New" }
      ]}
    />
  );
}

Vite + React Router

import { Link as RouterLink } from "react-router-dom";
import { Breadcrumbs } from "@ameshkin/nextcrumbs";
import { useReactRouterBreadcrumbs } from "@ameshkin/nextcrumbs/hooks/useReactRouterBreadcrumbs";

export function Trail() {
  const items = useReactRouterBreadcrumbs({ rootLabel: "Home" });
  return (
    <Breadcrumbs
      LinkComponent={RouterLink}
      linkProp="to"
      items={items}
    />
  );
}

You can also pass useLocation().pathname into usePathBreadcrumbs if you prefer the path helper.

Wrap the app in Vite as usual (BrowserRouter, MUI ThemeProvider). No Next.js plugins or "use client" directives are required for this path.

See also docs/vanilla-json.md and docs/react-router.md.


Quick Start (Next.js)

Optional. Use this only in a Next.js App Router project:

"use client";
import Link from "next/link";
import { NextCrumb } from "@ameshkin/nextcrumbs";
// Also available as: import { Breadcrumbs } from "@ameshkin/nextcrumbs";

export default function HeaderTrail() {
  return (
    <NextCrumb
      LinkComponent={Link}
      items={[
        { label: "Dashboard", href: "/" },
        { label: "Products", href: "/products" },
        { label: "New" }
      ]}
    />
  );
}

Auto from URL (Next App Router)

See full guide: docs/next-router.md

"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { Breadcrumbs, usePathBreadcrumbs } from "@ameshkin/nextcrumbs";

export default function AutoTrail() {
  const pathname = usePathname();
  const items = usePathBreadcrumbs(pathname, {
    baseHref: "/",
    rootLabel: "Home",
    labelMap: { new: "Create" },
    exclude: ["_private"]
  });

  return <Breadcrumbs LinkComponent={Link} items={items} />;
}

React Router

See full guide: docs/react-router.md

import { MemoryRouter, Routes, Route, Link as RouterLink } from "react-router-dom";
import { Breadcrumbs } from "@ameshkin/nextcrumbs";
import { useReactRouterBreadcrumbs } from "@ameshkin/nextcrumbs/hooks/useReactRouterBreadcrumbs";

function Trail() {
  const items = useReactRouterBreadcrumbs({
    rootLabel: "Home",
    exclude: [/^_/]
  });
  return <Breadcrumbs LinkComponent={RouterLink} linkProp="to" items={items} />;
}

export default function Demo() {
  return (
    <MemoryRouter initialEntries={["/catalog/hats"]}>
      <Routes>
        <Route path="/" element={<Trail />} />
        <Route path="/catalog/hats" element={<Trail />} />
      </Routes>
    </MemoryRouter>
  );
}

react-router-dom is an optional peer. Import the hook only from @ameshkin/nextcrumbs/hooks/useReactRouterBreadcrumbs (alias: useRRBreadcrumbs). Use linkProp="to" so React Router receives to while a native href remains for right-click open. The main package entry does not import React Router.


Subpath exports

Import path Contents
@ameshkin/nextcrumbs Breadcrumbs, NextCrumb, usePathBreadcrumbs, buildPathBreadcrumbs, getLinkRoutingProps, JSON-LD helpers + types
@ameshkin/nextcrumbs/breadcrumbs Component only
@ameshkin/nextcrumbs/hooks/usePathBreadcrumbs Path helper (client hook)
@ameshkin/nextcrumbs/hooks/useReactRouterBreadcrumbs React Router helper (useReactRouterBreadcrumbs, useRRBreadcrumbs)
@ameshkin/nextcrumbs/utils/buildPathBreadcrumbs RSC-safe pure path → crumbs helper
@ameshkin/nextcrumbs/utils/jsonld toJsonLd, BreadcrumbJsonLd, breadcrumbsToJsonLd (no "use client")
@ameshkin/nextcrumbs/package.json Package metadata

Published files live under dist/ (main / types / exports all point there).


Props

<Breadcrumbs />

Prop Type Default Description
items { label: string; href?: string; icon?: React.ReactNode; title?: string; external?: boolean }[] required The breadcrumb trail; last item usually has no href.
LinkComponent React.ElementType @mui/material/Link Custom link component (for example Next.js Link).
linkProp "href" | "to" "href" "to" for React Router. Always still sets native href so right-click / open in new tab works.
maxItems / itemsBeforeCollapse / itemsAfterCollapse / expandText number / string - First-class MUI collapse controls for deep trails.
size "small" | "medium" | "large" "medium" Crumb text size.
truncate boolean | number false Ellipsis long labels (true = 160px, or pass max width px).
jsonLdOrigin string - When set, also emits BreadcrumbList JSON-LD for these items (relative URLs resolve against it).
muiProps Omit<MUIBreadcrumbsProps,"children" | collapse props> - Extra props for MUI <Breadcrumbs />.
separatorIcon React.ReactNode ChevronRightIcon Icon/node placed between items.
homeLabel string "Home" Display label for the home crumb (homeHref).
homeHref string "/" Href that receives the automatic Home icon (not label match).
ariaLabel string "Breadcrumb" aria-label on the nav.
dense boolean false Tighter gap between items.
sx SxProps<Theme> - Root styles (default margin is 0).
itemSx / linkSx / currentSx / contentSx / iconSx / labelSx SxProps<Theme> - Style slots for crumbs.

usePathBreadcrumbs(pathname, options?) / buildPathBreadcrumbs(pathname, options?)

Same options. Prefer buildPathBreadcrumbs in Server Components (@ameshkin/nextcrumbs/utils/buildPathBreadcrumbs).

Option Type Default Description
baseHref string "/" Root href for the first crumb.
labelMap Record<string,string> {} Override labels by URL segment.
exclude string[] [] Skip specific segments.
decode boolean true decodeURIComponent each segment.
rootLabel string "Dashboard" Label for the root/home breadcrumb.
transformLabel (segment: string) => string - Custom label formatter.

useReactRouterBreadcrumbs(options?)

Import from @ameshkin/nextcrumbs/hooks/useReactRouterBreadcrumbs.

Option Type Default Description
rootLabel string - Optional first crumb label linking to /.
basePath string - Strip a leading base path when building crumbs.
decode boolean true Decode each segment before labeling.
exclude (string | RegExp)[] [] Skip segments by string or regex.
mapSegmentLabel (segment, index, segments) => string | null - Customize a label or return null to hide a segment.

Icon & Separator Examples

import Link from "next/link";
import NavigateNextIcon from "@mui/icons-material/NavigateNext";
import HomeOutlinedIcon from "@mui/icons-material/HomeOutlined";
import { Breadcrumbs } from "@ameshkin/nextcrumbs";

<Breadcrumbs
  LinkComponent={Link}
  separatorIcon={<NavigateNextIcon fontSize="small" />}
  items={[
    { label: "Home", href: "/", icon: <HomeOutlinedIcon /> },
    { label: "Products", href: "/products" },
    { label: "Gadgets" }
  ]}
/>;

Accessibility & SEO

  • Uses MUI's accessible <Breadcrumbs aria-label={ariaLabel}> (default "Breadcrumb").
  • Current page gets aria-current="page".
  • Minimal DOM footprint; last item is usually text without href.

JSON-LD Structured Data

Pass your real origin. Relative hrefs are left unresolved if origin is omitted (no example.com default).

import { Breadcrumbs } from "@ameshkin/nextcrumbs";

<Breadcrumbs items={items} jsonLdOrigin="https://yoursite.com" LinkComponent={Link} />

Or use the helpers:

import { Breadcrumbs, BreadcrumbJsonLd, breadcrumbsToJsonLd, toJsonLd } from "@ameshkin/nextcrumbs";

<BreadcrumbJsonLd crumbs={breadcrumbsToJsonLd(items)} origin="https://yoursite.com" />
<Breadcrumbs items={items} />

const jsonLd = toJsonLd(
  [{ name: "Home", href: "/" }, { name: "Products" }],
  { origin: "https://yoursite.com" }
);

See docs/vanilla-json.md.


Docs

Guide Path
Vite / any React + JSON-LD docs/vanilla-json.md
React Router docs/react-router.md
Next.js App Router (optional) docs/next-router.md
Subpath exports (CI / GitLab) docs/gitlab.md
Export & API changelog docs/changes.md
Docs index docs/README.md

Dependency Checks

npm ls @mui/material @mui/icons-material @emotion/react @emotion/styled react react-dom
# only if using the React Router subpath
npm ls react-router-dom

Troubleshooting

Can't resolve 'react-router-dom'

You are importing the React Router hook. Either install the peer or stop importing that subpath:

npm install react-router-dom
// React Router apps
import { useReactRouterBreadcrumbs } from "@ameshkin/nextcrumbs/hooks/useReactRouterBreadcrumbs";

// Next.js (no React Router)
import { Breadcrumbs, usePathBreadcrumbs } from "@ameshkin/nextcrumbs";

Package resolves to missing files (./public/...)

You are on 0.2.0. Upgrade:

npm i @ameshkin/nextcrumbs@^0.2.1

ERESOLVE with MUI 8/9 or X Charts

This package peers @mui/material@^7. Do not run npm audit fix --force to pull MUI 9. Keep your app on MUI 7 while using NextCrumbs 0.2.x.


FAQ

Note. NextCrumbs does not require Next.js. It is a React + MUI component that runs in Vite, CRA, Remix, and other React apps. The name comes from the original Next.js target. Next.js is optional. Use the answers below by topic.

Framework and bundler

Do I need Next.js?

No. Install the package and MUI peers, then render <Breadcrumbs />. No Next.js plugins or "use client" directives are required outside the App Router.

Does it work with Vite?

Yes. There is no Vite-specific plugin. See Quick Start (Vite / any React) and docs/vanilla-json.md.


Routing

Does it work with React Router?

Yes. Import the hook from the React Router subpath and pass LinkComponent={RouterLink} with linkProp="to":

import { useReactRouterBreadcrumbs } from "@ameshkin/nextcrumbs/hooks/useReactRouterBreadcrumbs";
// <Breadcrumbs LinkComponent={RouterLink} linkProp="to" items={items} />

linkProp="to" sets React Router's to and still keeps a native href (right-click open / middle-click). Install react-router-dom only when you use that subpath.

Do I need react-router-dom for Next.js?

No. Use the main entry and usePathBreadcrumbs. Only install React Router if you import @ameshkin/nextcrumbs/hooks/useReactRouterBreadcrumbs. If a bundler errors on that subpath, see Troubleshooting.


Appearance and SEO

How do I style the current (last) crumb?

Omit href on the last item so it renders as text. Style it with currentSx or your theme.

Can I disable icons?

Yes. Do not pass icon on items. The automatic Home icon only appears when href === homeHref (default "/"). Change homeHref or pass your own icon if you want different behavior.

Can I emit JSON-LD from <Breadcrumbs>?

Yes. Pass jsonLdOrigin (your real site origin):

<Breadcrumbs items={items} jsonLdOrigin="https://yoursite.com" />

Versions and peers

Which version should I install?

Use 0.2.1+. Do not use 0.2.0 (broken exports pointing at missing ./public/*).

npm i @ameshkin/nextcrumbs@^0.2.1

Why is MUI capped at ^7?

A wider peer like >=7 lets npm pull MUI 8 or 9, which breaks apps still on MUI 7. Keep NextCrumbs on ^7 for 0.2.x.


More guides

Topic Doc
Vite / no Next.js / JSON-LD docs/vanilla-json.md
React Router docs/react-router.md
Next.js App Router (optional) docs/next-router.md
Subpath exports docs/gitlab.md
Changelog docs/changes.md

Contributing

npm ci
npm run ci

npm run ci runs typecheck, unit tests, and build (same pipeline as .github/workflows/ci.yml).

Keep MUI peers on ^7. Do not widen them to >=7.


License

MIT

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages