Quickstart
Choose your stack below. The steps update to match, and you get a prompt to hand to your coding assistant — with the right docs links and guidance — so it can wire Breadcrumb up for you.
Hand it to your assistant
Copy this into Claude Code, Cursor, or any coding assistant. It names your stack, links the docs pages that matter, and lists what to do.
I'm adding Breadcrumb — embeddable LLM tracing that stores traces in my own database — to my Next.js app. I'll store traces in Postgres and instrument with the Vercel AI SDK.
Relevant docs:
- Quickstart: https://breadcrumb.sh/docs/quickstart/
- Mounting the handler (Next.js): https://breadcrumb.sh/docs/frameworks/nextjs/
- Mounting the dashboard: https://breadcrumb.sh/docs/dashboard/
- Database & adapters: https://breadcrumb.sh/docs/database/
- Migrations: https://breadcrumb.sh/docs/migrations/
- Instrumenting (the Vercel AI SDK): https://breadcrumb.sh/docs/instrumenting/ai-sdk/
- Configuration: https://breadcrumb.sh/docs/configuration/
Please help me set it up:
1. Install @breadcrumb-sh/core, @breadcrumb-sh/react, and the pg driver.
2. Create a shared bc instance in lib/breadcrumb.ts using the postgres() adapter with basePath "/api/breadcrumb".
3. Mount bc.handler at /api/breadcrumb for Next.js. This is the JSON API, not a UI.
4. Render <BreadcrumbDashboard api="/api/breadcrumb" basePath="/admin/traces" /> on a page at /admin/traces, and import "@breadcrumb-sh/react/styles.css" once above it.
5. Instrument my LLM calls with the Vercel AI SDK.
6. Add the authorize option to protect the API, and guard the dashboard page with my app's own auth, before shipping.
Good to know:
- The dashboard is a React component mounted at a route I own, not something the handler serves. The API and the page are two separate routes.
- Give the dashboard a container with a height; it fills its parent.
- The schema is created automatically in development. For production, generate migration files with "npx breadcrumb generate --database $DATABASE_URL", commit them, and set migrations: "manual".
- On serverless, call "await bc.flush()" (or waitUntil(bc.flush())) before the response returns so no spans are lost.1. Install
Install the core package and the driver for your database.
npm i @breadcrumb-sh/core @breadcrumb-sh/react pgnpm i @breadcrumb-sh/core @breadcrumb-sh/react better-sqlite32. Create the instance
Create one instance and export it, pointed at your database.
// lib/breadcrumb.ts
import { breadcrumb } from "@breadcrumb-sh/core";
import { postgres } from "@breadcrumb-sh/core/adapters";
export const bc = breadcrumb({
database: postgres(process.env.DATABASE_URL!),
basePath: "/api/breadcrumb",
authorize: (req) => isAdmin(req),
});// lib/breadcrumb.ts
import { breadcrumb } from "@breadcrumb-sh/core";
import { sqlite } from "@breadcrumb-sh/core/adapters";
export const bc = breadcrumb({
database: sqlite(".breadcrumb/dev.db"),
basePath: "/api/breadcrumb",
});3. Set up the schema
Breadcrumb creates its tables automatically on first use, so in development there's nothing to run. When you deploy to Postgres, generate a migration — see Migrations.
Apply the schema to your database:
npx breadcrumb migrate --database $DATABASE_URLIt's also created automatically on first use. For production, generate migration files you commit and set migrations: "manual" — see Migrations.
4. Mount the API
Mount bc as a catch-all at your basePath. This serves the JSON API your traces are read and written through.
// app/api/breadcrumb/[...path]/route.ts
import { toNextHandler } from "@breadcrumb-sh/core/next";
import { bc } from "@/lib/breadcrumb";
export const { GET, POST, DELETE } = toNextHandler(bc);import { Hono } from "hono";
import { bc } from "./breadcrumb";
const app = new Hono();
app.all("/api/breadcrumb", (c) => bc.handler(c.req.raw));
app.all("/api/breadcrumb/*", (c) => bc.handler(c.req.raw));import express from "express";
import { toNodeHandler } from "@breadcrumb-sh/core/node";
import { bc } from "./breadcrumb";
const app = express();
app.use("/api/breadcrumb", toNodeHandler(bc));// src/routes/api/breadcrumb/[...path]/+server.ts (SvelteKit)
import { bc } from "$lib/breadcrumb";
export const GET = ({ request }) => bc.handler(request);
export const POST = ({ request }) => bc.handler(request);5. Mount the dashboard
The dashboard is a React component you render at a route of your own, so it sits behind your auth and inside your layout.
// 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, above the dashboard:
// app/layout.tsx — once, anywhere above the dashboard
import "@breadcrumb-sh/react/styles.css";Two routes rather than one, because the App Router won't put a route handler and a page on the same segment. See Dashboard.
import { BreadcrumbDashboard } from "@breadcrumb-sh/react";
import "@breadcrumb-sh/react/styles.css";
// Render this wherever your app renders React, on a route you guard yourself.
<div style={{ height: "100dvh" }}>
<BreadcrumbDashboard api="/api/breadcrumb" basePath="/admin/traces" />
</div>;import { BreadcrumbDashboard } from "@breadcrumb-sh/react";
import "@breadcrumb-sh/react/styles.css";
// Render this wherever your app renders React, on a route you guard yourself.
<div style={{ height: "100dvh" }}>
<BreadcrumbDashboard api="/api/breadcrumb" basePath="/admin/traces" />
</div>;import { BreadcrumbDashboard } from "@breadcrumb-sh/react";
import "@breadcrumb-sh/react/styles.css";
// Render this wherever your app renders React, on a route you guard yourself.
<div style={{ height: "100dvh" }}>
<BreadcrumbDashboard api="/api/breadcrumb" basePath="/admin/traces" />
</div>;6. Instrument
Capture a trace from your LLM calls.
import { generateText } from "ai";
const { text } = await generateText({
model: openai("gpt-5"),
prompt,
experimental_telemetry: bc.telemetry({ functionId: "generate-answer" }),
});await bc.trace("support-reply", { userId }, async (t) => {
t.set({ input: prompt });
const answer = await callModel(prompt);
t.set({ output: answer, model: "gpt-5", inputTokens, outputTokens });
});Run your app, trigger the code, and open /admin/traces. Your run is there, with each step nested underneath.
Next steps
- Dashboard: props, custom pages, and theming.
- Frameworks: more detail on mounting.
- Local development and Production: how the setup differs.
- Migrations: how the schema is created.