Deployment (Vercel)

Next.js 16 on Vercel. Runs on Fluid Compute by default — no Edge-specific code needed.

First deploy

  1. Push repo to GitHub.
  2. Vercel dashboard → New Project → import repo.
  3. Framework preset: Next.js (auto-detected).
  4. Add environment variables (see ../getting-started/environment.md).
  5. Deploy.

Environment variables

Minimum for production:

DATABASE_URL=...
NEXTAUTH_SECRET=<random>
NEXTAUTH_URL=https://<your-domain>
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
AWS_REGION=us-east-1
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_PRO_PRICE_ID=price_...
UPSTASH_REDIS_REST_URL=...
UPSTASH_REDIS_REST_TOKEN=...

Set per environment — Development / Preview / Production.

CLI sync

vercel link
vercel env pull .env.local

Webhooks on production

After first deploy, register webhook endpoints in each provider:

Provider URL
Stripe https://<host>/api/webhooks/stripe
AWS SNS (SES events) https://<host>/api/webhooks/ses

Stripe: select checkout.session.completed, customer.subscription.deleted, invoice.payment_failed. Copy signing secret → STRIPE_WEBHOOK_SECRET.

SNS: HTTPS subscription. The app auto-confirms the subscription (fetches SubscribeURL on SubscriptionConfirmation message).

Database

Use Vercel Marketplace → Neon integration to provision and auto-populate DATABASE_URL. Alternatively: Neon console → create project → copy pooled connection string.

Function regions

No explicit region pinning. Defaults per Vercel project config. For lowest latency, match the Vercel function region to the Neon project region.

Cold starts

Fluid Compute reuses instances across requests — warm instances retain the Neon sql client singleton and the AWS SDK clients. No tuning needed.

Build

npm run build

Vercel runs this automatically. Cron schedules live in vercel.ts — add rewrites / headers there if needed.

Post-deploy smoke test

curl https://<host>/api/v1/emails -H "Authorization: Bearer sok_test_..."
# Expect: 401 if unauth'd, 200 with empty data if key valid but no sends yet