DuckVizBeta
Packages

Quickstart for developers

Scaffold a Next.js starter with Explorer, Dashboard, Report, and Deck wired to a demo dataset in under a minute.

The fastest way to get DuckViz components rendering against real data is the CLI scaffolder. One command, four working routes, no boilerplate.

Are you here to use the hosted app?

Try the analyst quickstart instead — upload a file at app.duckviz.com and an AI-generated dashboard appears in two minutes.

Prerequisites

1. Scaffold

npx duckviz create-app my-app
cd my-app

The CLI auto-detects your package manager (npm / pnpm / yarn / bun) and runs the install. Override with --pm, skip with --no-install. Full options in the CLI docs.

2. Add your token

cp .env.local.example .env.local

Open .env.local and paste your token:

DUCKVIZ_TOKEN=dvz_live_your_token_here

The token stays server-side. The scaffolded SDK proxy at app/api/duckviz/[...route] is what calls DuckViz with the bearer attached — the browser only ever sees its own origin.

3. Run dev

npm run dev    # or pnpm dev / yarn dev / bun dev

Open http://localhost:3000/explorer. Four routes are live:

RouteWhat you'll see
/explorerThree-panel data explorer over a demo t_users table. AI widget recommendations stream into the right panel.
/dashboardA 4-widget dashboard (Total users, Total MRR, Users by country, Signups over time) on a draggable react-grid-layout grid.
/reportYoopta-based report editor with the chart-rasterization + PDF/DOCX/PPTX export pipeline.
/deckSlide-deck mode against the same widgets.

All four read from lib/demo-dashboard.ts and the useUsersDataset() hook in lib/use-users.ts.

What just happened

FilePurpose
app/api/users/route.tsDemo data source. Returns 1,000 fake users (fake-users.ts). Replace with your real backend.
app/api/duckviz/[...route]/route.tsSDK proxy. Reads DUCKVIZ_TOKEN server-side and forwards every browser AI call upstream.
lib/custom-fetch.tsRewrites /api/widget-flow/*/api/duckviz/widget-flow/* so the components hit the proxy. Threaded into <Explorer>, <ReportBuilder>, <DeckBuilder> as their customFetch prop.
lib/use-users.tsOne-shot ingest of the demo data into a t_users DuckDB-WASM table. Cached so all four routes share the same in-memory table.
lib/demo-dashboard.tsThe 4-widget config — KPI, KPI, bar, line — written as plain DashboardConfig. Each widget's dataKey is a DuckDB SQL string.
app/providers.tsxWraps the app in <DuckvizThemeProvider> and <DuckvizDBProvider persistence batchSize={5000}>.

Replace the demo with your data

Three places to touch:

1. Your data source. Either edit app/api/users/route.ts to fetch from your DB, or add a new route — app/api/orders/route.ts, etc. — and a sibling hook in lib/.

2. The dashboard config. Edit lib/demo-dashboard.ts. Each widget is a { id, type, title, dataKey, layout }type comes from the chart registry, dataKey is a DuckDB SQL query against your ingested table, layout is a 12-column react-grid-layout slot.

3. The dataset wiring. Update lib/use-users.ts (or its replacement) to point at your new endpoint and pick the right tableName. The scaffold uses t_users everywhere — pick whatever prefix matches your domain.

Next steps

  • Chart types — all 80+ widget types and the columns each one expects
  • Datasets mode — how <Explorer> / <Dashboard> auto-ingest DuckvizDataset[] on mount, and when to skip it
  • Custom themes — swap the preset, build your own token set
  • Server proxy setup — what the scaffolded proxy does, and how to add auth checks / rate limiting on top
  • Next.js integration guide — the same wiring explained step-by-step, useful for retrofitting an existing app

Troubleshooting

AI calls 404 on /api/widget-flow/*

You're on a scaffold from CLI 0.3.0 or 0.3.1. The SDK proxy was wired but the components weren't told to use it — lib/custom-fetch.ts and the customFetch prop threading shipped in 0.3.2. Re-scaffold or backport the change.