Clone, configure, migrate, and run the project
Local Development
A step-by-step guide to running Surflink locally.
Prerequisites
- Node.js 20.9+ (required by Next.js 16; LTS recommended). Note: there is no
enginesfield or.nvmrc; the version is by convention. - npm (or yarn)
- A Supabase project (supabase.com)
- The Supabase CLI (for migrations)
- A SurfVision AI backend endpoint (Modal cloud URL, or a local server) for video analysis
- (Optional) Google AI Studio key for AI coaching feedback
- (Optional) Stripe, Resend, Frame.io, APNs for billing, email, video import, and push
1. Clone and install
git clone https://github.com/surflink-ai/surflink-app.git
cd surflink-app
npm install
2. Configure environment
Create .env.local in the project root. See the full Environment Variables reference -- at minimum you need the Supabase keys, a Modal API URL, and the stream signing secret.
3. Set up the database
The authoritative schema is the ordered set of migrations in supabase/migrations/. Apply them with the Supabase CLI:
supabase link --project-ref <your-project-ref>
supabase db push
Or run each file in supabase/migrations/ in chronological (filename) order from the dashboard SQL Editor.
supabase/schema.sqlis a read-only snapshot of the livepublicschema (generated via catalog introspection) kept for reference. The migrations are authoritative -- don't provision a database from the snapshot alone, since it omits roles, grants, the auth/storage schemas, extensions, and seed data.
4. Create storage buckets (required, manual)
The app reads/writes two Supabase Storage buckets that no migration creates. Create them manually in the Supabase dashboard (Storage -> New bucket):
| Bucket | Purpose |
|---|---|
raw-uploads | Resumable upload target for raw clips before analysis |
session-videos | Processed videos cached from the AI backend (CDN) |
If these don't exist, uploads and the post-analysis CDN transfer will fail.
5. Seed achievements (optional)
There is no SQL seed file. To populate achievement definitions, call the idempotent endpoint once the app is running:
curl -X POST http://localhost:3000/api/achievements/seed
6. Run the dev server
npm run dev
Open http://localhost:3000, sign up as a coach, and you'll land on the dashboard.
Available scripts
| Command | Description |
|---|---|
npm run dev | Start the development server |
npm run build | Create a production build |
npm run start | Start the production server |
npm run lint | Run ESLint |
npm test | Run Vitest in watch mode |
npm run test:run | Run the test suite once (CI) |
A note on client-side compression
Client-side FFmpeg compression requires SharedArrayBuffer, which needs cross-origin isolation headers (Cross-Origin-Embedder-Policy: require-corp and Cross-Origin-Opener-Policy: same-origin). These are not set -- next.config.mjs is empty -- so the compression toggle is effectively disabled in production until you add them. Uploads work fine without compression.