DocsArchitecture
App structure, patterns, and data flow
Architecture
Surflink is a Next.js 16 (React 19) app using the App Router, with Supabase for database/auth/storage and a set of external services for AI, video, payments, and notifications. JavaScript throughout (not TypeScript).
Directory layout
surflink-app/
├── src/
│ ├── app/ # App Router pages and API routes
│ │ ├── layout.js # Root layout (fonts, theme, service worker)
│ │ ├── page.js # Landing page
│ │ ├── globals.css # CSS variables, component classes
│ │ ├── login/ signup/ # Auth pages
│ │ ├── auth/callback/ # OAuth/session callback (route handler)
│ │ ├── dashboard/ # Coach dashboard
│ │ ├── sessions/ # Session list + detail (coaching workspace)
│ │ ├── upload/ # Video upload + Frame.io import
│ │ ├── students/ # Athlete roster + detail + CSV import
│ │ ├── student/ # Student portal
│ │ ├── drills/ lessons/ # Drill library, lesson scheduling
│ │ ├── plans/ # Training plans + goals
│ │ ├── competitions/ circuits/ # Competition + circuit management
│ │ ├── analytics/ # Analytics + competition analytics
│ │ ├── billing/ # Coaching-package marketplace
│ │ ├── org/ # Org settings + member invite acceptance
│ │ ├── compare/ journal/ community/ messages/
│ │ ├── watchlist/ admin/dedup/
│ │ ├── club/ p/ reports/ # Public: club enroll, public profile, reports
│ │ ├── docs/ # This documentation site
│ │ └── api/ # API route handlers (see API Reference)
│ ├── components/ # React components
│ ├── hooks/ # Custom hooks (useSessionData, useAthleteData, ...)
│ ├── lib/ # Shared utilities (see below)
│ ├── middleware.js # Auth + route protection + billing gating
│ └── __tests__/ # Vitest suite
├── apple/ # Native Apple Watch + iOS companion app
├── public/ # Static assets, PWA manifest, service worker
├── supabase/migrations/ # Authoritative ordered DB migrations
└── vercel.json # Cron job configuration
Key patterns
- Client components + direct Supabase queries. Most pages use
'use client'and theuseAuth()hook (fromAuthProvider) for the current user, coach profile, current org, permissions, and enabled modules. Reads go through the browser Supabase client (RLS-scoped). - DashboardLayout. Every authenticated coach page is wrapped in
DashboardLayout, which renders the grouped sidebar (Sidebar.js) and a mobile navbar. Sidebar items are filtered by enabled modules. - Server route handlers. Privileged operations (video pipeline, Stripe, orgs/RBAC, notifications, crons) live in
src/app/api/*and use the server or admin Supabase clients. - Three Supabase clients.
supabase-browser.js(anon, client),supabase-server.js(SSR, cookie-bound),supabase-admin.js(service-role, server only).
Video pipeline (overview)
- Upload raw clips to Supabase Storage (
raw-uploadsbucket) via resumable TUS. - Analyze --
POST /api/clips/analyzesigns the clip and forwards it to the SurfVision backend's/analyze. - Poll
GET {base}/status/{job_id}every 3s. - Store -- on completion,
POST /api/clips/storedownloads the processed video from{base}/result/{job_id}/videoand re-uploads it to thesession-videosbucket, saving stats. - Stream through the HMAC-gated
/api/video/streamproxy.
See AI Video Pipeline for the full detail.
Theming and fonts
CSS custom properties in globals.css (dark/light), managed by ThemeProvider (wrapping next-themes). Three Google fonts via next/font: Outfit (display), Plus Jakarta Sans (body), JetBrains Mono (mono).