Live: clippers-command-center.vercel.app
A desktop analytics dashboard for avid LA Clippers fans. Three modes that blend into one continuous experience:
- Live Game Mode — dense box score, rotating "provable" insights, league-context side panels, Vegas odds, polling every ~12s during Clippers games.
- Between-Games Mode — team snapshot, upcoming schedule, player trend summaries, macro insights.
- Historical Explorer — 3 seasons of game-by-game data with drill-through to box scores and trend charts.
Provable insights, not vibe stats. Every headline on the dashboard is generated by a deterministic engine that must verify the claim against stored data before displaying it. If it can't prove "first time in franchise history a Clipper has scored 50+ in a quarter" from the DB, it doesn't show it. Each insight stores the query that produced it.
Real-time without flicker. The live page uses SWR over a Next.js API that merges a short-lived cache with snapshots written by a background poller. Stale reads surface a banner instead of silently serving old numbers.
One operator, full pipeline. Schedule sync, odds sync, live polling, finalization, stat computation, and insight generation all run as separate scripts wired to Vercel Cron — no hosted workflow engine, no queue, no magic.
- Next.js 16 (App Router, Turbopack) + React 19 + TypeScript
- Neon Postgres via
postgres - shadcn/ui + Tailwind v4, Recharts
- SWR for client data,
tsxfor ops scripts - Vitest for unit tests
- Hosted on Vercel with Vercel Cron triggering the data pipeline
balldontlie.io— NBA schedule, games, box scores (historical + finalization)stats.nba.com/ NBA CDN — live in-game polling and schedule backfillthe-odds-api.com— Vegas odds (display + insight annotation; no betting)
app/ — Next.js App Router: /live, /home, /schedule, /history, /players
components/ — UI (live/, nav/, skeletons/, stale-banner/, ui/)
hooks/ — useLiveData, useInsightRotation
src/lib/ — DB client, insight engine, domain utils + tests
scripts/ — backfill, compute-stats, sync-schedule, poll-live, sync-odds, finalize-games, generate-insights
docs/ — ARCHITECTURE.md, API_SPEC.md, DB_SCHEMA.sql, DATA_DICTIONARY.md
cp .env.example .env.local # fill DATABASE_URL, BALLDONTLIE_API_KEY, ODDS_API_KEY, CRON_SECRET
npm install
npm run db:schema # applies docs/DB_SCHEMA.sql to Neon
npm run sync-schedule # seed a season
npm run compute-stats
npm run dev # http://localhost:3000Tests:
npm test # vitest
npm run lintData-pipeline scripts:
npm run sync-schedule # schedule from BDL
npm run sync-odds # Vegas odds
npm run poll-live # NBA live polling (runs on Vercel Cron in prod)
npm run finalize-games # lock box scores after each game
npm run generate-insights # run insight engine over latest state
npm run backfill -- --season 2024 # historical ingestion- 18 routes deployed to production
- 266 commits, 16 phases shipped
- Tests cover the domain layer: insight engine, odds math, history, home, live, players, schedule
- Desktop only (min-width 1024px); mobile deferred
Product definition, architecture, and the live API contract are in docs/.