Skip to content

Deployment

Deploy as two Vercel projects from the same Git repo. Users see one domain; Vercel routes by path.

PathProjectRoot directory
/, /blog/*, /docs/*Marketingapps/web
/app/*Dashboard + APIapps/app
  1. App project — create a Vercel project with root directory apps/app. Install the Supabase integration (sets DATABASE_URL, SUPABASE_URL, keys).
  2. Web project — create a second project with root directory apps/web. Attach your custom domain here.
  3. Update the rewrite in apps/web/vercel.json — set the destination to your app project’s Vercel URL:
{
"rewrites": [
{
"source": "/app/:path*",
"destination": "https://your-app-project.vercel.app/app/:path*"
}
]
}
  1. Run migrations against Supabase using the direct Postgres URL (port 5432):
Terminal window
DATABASE_URL=postgresql://...:5432/postgres pnpm db:migrate
  1. Create a Supabase Storage bucket matching SUPABASE_STORAGE_BUCKET (default: uploads).

Set these in the app Vercel project:

BETTER_AUTH_URL=https://yourdomain.com/app
NEXT_PUBLIC_APP_URL=https://yourdomain.com/app
PUBLIC_WEB_URL=https://yourdomain.com
PUBLIC_APP_URL=https://yourdomain.com/app
CRON_SECRET=your-random-secret

Use the pooler URL (port 6543) for DATABASE_URL at runtime.

Set PUBLIC_WEB_URL and GA vars in the web project.

Job typeProductionLocal dev
Cron (sendWeeklyDigest)Vercel Cron → /app/api/cron/weekly-digestpnpm jobs:worker or curl with CRON_SECRET
Queue (processUpload)Inline in API (default)Same

Optional Redis.io for queued uploads:

REDIS_URL=rediss://default:...@....redis.io:6379

When REDIS_URL is set, run pnpm jobs:worker on an external host (not Vercel) to consume BullMQ jobs.

Unchanged — two processes:

Terminal window
pnpm dev # Astro :4321 + Next :3000
pnpm jobs:worker # optional local cron + queues