Vercel deployment, env vars, and PWA config
Deployment
Surflink is designed to deploy on Vercel as a standard Next.js application.
Vercel Deployment
Quick Deploy
- Connect your GitHub repository to Vercel
- Vercel auto-detects the Next.js framework
- Configure environment variables in the Vercel dashboard
- Deploy
Build Settings
The default Next.js build configuration works out of the box:
| Setting | Value |
|---|---|
| Framework | Next.js |
| Build Command | next build |
| Output Directory | .next |
| Install Command | npm install |
| Node.js Version | 18.x |
Environment Variables
Set all required environment variables in Vercel's project settings:
Required
| Variable | Description |
|---|---|
NEXT_PUBLIC_MODAL_API_URL | Modal (SurfVision) API base URL |
NEXT_PUBLIC_SUPABASE_URL | Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Supabase public/anon key |
RESEND_API_KEY | Resend email API key |
RESEND_FROM_EMAIL | Email sender address |
STREAM_SIGNING_SECRET | HMAC secret for video stream tokens |
Optional (Frame.io)
| Variable | Description |
|---|---|
FRAMEIO_CLIENT_ID | Frame.io OAuth client ID |
FRAMEIO_CLIENT_SECRET | Frame.io OAuth client secret |
FRAMEIO_REDIRECT_URI | Must point to your production domain: https://yourdomain.com/api/auth/frameio/callback |
Optional (Push Notifications)
| Variable | Description |
|---|---|
APNS_KEY_ID | APNs key ID |
APNS_TEAM_ID | Apple Developer Team ID |
APNS_PRIVATE_KEY | APNs .p8 private key |
APNS_BUNDLE_ID | iOS app bundle ID |
APNS_ENVIRONMENT | Set to production for live deployments |
PWA Configuration
Web App Manifest
The PWA manifest is at public/manifest.json and configures:
- App name: Surflink
- Theme color:
#97FB57(accent mint) - Display: Standalone
- Categories: Sports, Education, Productivity
- Icons: Multiple sizes for various devices
Service Worker
The service worker at public/sw.js is registered on page load via a script in the root layout. It provides:
- Basic offline caching strategy
- Asset caching for faster subsequent loads
The service worker is registered in src/app/layout.js:
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js').catch(() => {})
})
}
CORS & Headers
Video Streaming
The /api/video/stream endpoint requires special handling:
- Excluded from auth middleware to avoid 431 (Header Too Large) errors from range requests
- Protected by HMAC-signed tokens instead (
/api/video/signissues time-limited tokens) - Supports byte-range requests for video scrubbing
- Allowlists Modal, Supabase, and Frame.io as video sources
SharedArrayBuffer
FFmpeg WASM (used for client-side video compression) requires SharedArrayBuffer, which needs these headers:
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
Configure these in next.config.mjs or Vercel's headers configuration if client-side compression is needed in production.
Database Deployment
The Supabase database is managed separately:
- Create a Supabase project at supabase.com
- Run
supabase/schema.sqlin the SQL Editor - Copy the project URL and anon key to your environment variables
- RLS policies ensure data isolation without additional server-side checks
Monitoring
- Vercel Analytics -- Built-in performance monitoring
- Supabase Dashboard -- Database metrics, auth logs, storage usage
- Modal Dashboard -- AI processing job status and logs