Clone, configure, migrate, and run the project
Local Development
There is no staging. Local dev points at the production database with real users' data. Treat every write as real.
Prerequisites
- Node.js 24 (
.nvmrcand theenginesfield both say so) and npm. - A Supabase project and the Supabase CLI (for migrations).
- A SurfVision endpoint (the Modal cloud URL, or a local/self-hosted server) for video analysis.
- Optional: Google AI Studio key (guided-review voice-note transcripts), Mapbox token (wearable maps), Stripe, Resend, Twilio, Frame.io, APNs, Web Push keys for their respective features.
1. Clone and install
git clone https://github.com/surflink-ai/surflink.git surflink-app
cd surflink-app
npm ci
2. Configure
Create .env.local. The minimum to boot is the Supabase URL, anon key and service-role key, a SurfVision URL, and the stream signing secret — see Environment Variables.
3. Database
The schema is the ordered set of migrations in supabase/migrations/:
supabase link --project-ref <your-project-ref>
supabase db push
Never edit an applied migration; add a new timestamped file. npm run build regenerates src/lib/migrationManifest.json (the prebuild hook) — commit it with the migration. A daily migration-drift cron compares the manifest with the live ledger.
4. Storage buckets
See Database & Migrations for the bucket list; the analysis buckets are created by hand in the Supabase dashboard.
5. Run
npm run dev # http://localhost:3000
Scripts
| Command | Description |
|---|---|
npm run dev / build / start | Next.js dev server, production build, production server |
npm run lint | ESLint (baseline: 0 errors) |
npm test / npm run test:run | Vitest watch / single run |
npm run handbook:check | Validate the internal handbook (frontmatter, links, cites, prose drift, generated files) |
npm run handbook:build / handbook:status | Regenerate the handbook's generated files / the live status board |
npm run build:guide | Rebuild the invited-coach PDF from the docs source (needs Chrome) |
npm run analyze | Build with the bundle analyzer |
Definition of done
Tests green locally (npm run test:run) → lint clean → handbook chapter updated if its cited files changed → ADR recorded if behaviour changed → conventional commit → push → verify /api/health and the feature in production. Vercel deploys every push to main whether or not CI passes, so the local test run is the real gate.
Client-side compression
The Compress before upload toggle needs SharedArrayBuffer, which requires cross-origin isolation headers (Cross-Origin-Embedder-Policy: require-corp, Cross-Origin-Opener-Policy: same-origin). They are not set, so compression is unavailable in production; uploads work without it.