Next.js
A Next.js setup has two routes: a catch-all route handler for the API, and a page for the dashboard.
The API
Create app/api/breadcrumb/[...path]/route.ts, matching the basePath you
passed to breadcrumb():
import { toNextHandler } from "@breadcrumb-sh/core/next";
import { bc } from "@/lib/breadcrumb";
export const { GET, POST, DELETE } = toNextHandler(bc);
toNextHandler returns one function per method; export the ones you need.
DELETE is what revoking an MCP key uses.
The dashboard
Create app/admin/traces/[[...slug]]/page.tsx:
import { BreadcrumbDashboard } from "@breadcrumb-sh/react";
export default function TracesPage() {
return (
<div style={{ height: "100dvh" }}>
<BreadcrumbDashboard api="/api/breadcrumb" basePath="/admin/traces" />
</div>
);
}
Then import the stylesheet once in app/layout.tsx:
import "@breadcrumb-sh/react/styles.css";
Two routes rather than one because the App Router will not put a route.ts and
a page.tsx on the same segment. The optional catch-all is what gives each
trace a shareable URL. See Dashboard for props, custom
pages, and server rendering deep links.
TIP
On serverless (including Vercel), flush spans before the function returns so none are lost when the runtime freezes. See Production.
If you use better-sqlite3 in development, add it to serverExternalPackages
in next.config.ts so Next leaves the native module alone:
export default { serverExternalPackages: ["better-sqlite3"] };
Next steps
- Dashboard: props, custom pages, and theming.
- Database & migrations: choose an adapter.
- Instrumenting: capture your first trace.