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
- Node.js 18+ or Bun 1.2+
- A DuckViz account — sign up at app.duckviz.com (free credits, no card)
- A DuckViz API token — mint one at app.duckviz.com/settings/tokens
1. Scaffold
npx duckviz create-app my-app
cd my-appThe 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.localOpen .env.local and paste your token:
DUCKVIZ_TOKEN=dvz_live_your_token_hereThe 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 devOpen http://localhost:3000/explorer. Four routes are live:
| Route | What you'll see |
|---|---|
/explorer | Three-panel data explorer over a demo t_users table. AI widget recommendations stream into the right panel. |
/dashboard | A 4-widget dashboard (Total users, Total MRR, Users by country, Signups over time) on a draggable react-grid-layout grid. |
/report | Yoopta-based report editor with the chart-rasterization + PDF/DOCX/PPTX export pipeline. |
/deck | Slide-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
| File | Purpose |
|---|---|
app/api/users/route.ts | Demo data source. Returns 1,000 fake users (fake-users.ts). Replace with your real backend. |
app/api/duckviz/[...route]/route.ts | SDK proxy. Reads DUCKVIZ_TOKEN server-side and forwards every browser AI call upstream. |
lib/custom-fetch.ts | Rewrites /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.ts | One-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.ts | The 4-widget config — KPI, KPI, bar, line — written as plain DashboardConfig. Each widget's dataKey is a DuckDB SQL string. |
app/providers.tsx | Wraps 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-ingestDuckvizDataset[]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.