Deploy at Vercel
Deploy your frontend and backend at Vercel.
Overview
ZeroStarter can be deployed to Vercel for both the frontend (Next.js) and backend (Hono) applications. This guide covers the deployment configuration for both parts of the application.
Prerequisites
- A Vercel account
- Your repository pushed to GitHub, GitLab, or Bitbucket
- A PostgreSQL database (e.g., Neon, Supabase, or Railway)
Frontend Deployment
Configuration
Each workspace includes a vercel.json with the correct install, build, and framework settings. Vercel reads this automatically when you set the root directory.
| Option | Value |
|---|---|
| Root Directory | web/next |
| Framework | Next.js |
| Install Command | cd ../.. && bun install --ignore-scripts |
| Build Command | cd ../.. && turbo build --filter=@web/next |
| Bun Version | 1.3.10 |
Environment Variables
.env.example is the source of truth for the full variable set. Add at least these in Vercel project settings:
NODE_ENV=production
NEXT_PUBLIC_APP_URL=https://your-frontend-domain.vercel.app
NEXT_PUBLIC_API_URL=https://your-backend-domain.vercel.app
# Optional: Analytics
NEXT_PUBLIC_POSTHOG_HOST=https://eu.i.posthog.com
NEXT_PUBLIC_POSTHOG_KEY=your_posthog_key
# Optional: Feedback
NEXT_PUBLIC_USERJOT_URL=your_userjot_urlNEXT_PUBLIC_NODE_ENV is required by the web env schema but is derived automatically from NODE_ENV, so you do not set it as a separate variable.
Backend Deployment
Configuration
| Option | Value |
|---|---|
| Root Directory | api/hono |
| Framework | Hono |
| Install Command | cd ../.. && bun install --ignore-scripts |
| Build Command | cd ../.. && bun .github/scripts/migrate-on-deploy.ts && turbo build:vercel --filter=@api/hono |
| Output Directory | vercel-bundle |
| Bun Version | 1.3.10 |
Migrations on deploy
Production and canary builds need a reachable POSTGRES_URL at BUILD time, since migrations run during the build. PR previews skip migrating against the shared database.
The backend build command runs .github/scripts/migrate-on-deploy.ts before building. That script applies pending migrations with bun run db:migrate, but only when VERCEL_ENV=production or VERCEL_GIT_COMMIT_REF=canary; PR previews skip it (an unmerged migration must not run against the shared database). Because the migration runs at build time, production and canary builds need a reachable POSTGRES_URL available during the build.
Environment Variables
.env.example is the source of truth for the full variable set. Add at least these in Vercel project settings:
NODE_ENV=production
HONO_APP_URL=https://your-backend-domain.vercel.app
HONO_TRUSTED_ORIGINS=https://your-frontend-domain.vercel.app
BETTER_AUTH_SECRET=your_secret_key
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
POSTGRES_URL=your_postgres_connection_stringHONO_PORT exists in the env schema (default 4000) but is unused on Vercel, where the serverless runtime manages the port, so there is no need to set it.
Deployment Steps
Frontend and backend must be deployed as two separate Vercel projects. Each project has its own configuration, environment variables, and deployment lifecycle.
Backend Project (deploy first)
- Go to Vercel dashboard and click "Add New Project"
- Select your ZeroStarter repository
- Set Root Directory to
api/hono - Add backend environment variables (see above)
- Click "Deploy"
- Copy the deployment URL (e.g.,
https://your-api.vercel.app)
Frontend Project
- Go to Vercel dashboard and click "Add New Project"
- Select the same ZeroStarter repository
- Set Root Directory to
web/next - Add frontend environment variables, using the backend URL from step 6 above for
NEXT_PUBLIC_API_URL - Click "Deploy"
The frontend and backend are two separate Vercel projects. Environment variables are set per-project and do not propagate between them; deployments are triggered independently.
Custom Domains
After deployment, configure custom domains:
- Go to your project settings in Vercel
- Navigate to "Domains"
- Add your custom domain
- Update DNS records as instructed
- Update environment variables with the new domain URLs
Notes
- Deploy the backend first to get the API URL for the frontend environment variables
- Make sure to update OAuth callback URLs in GitHub/Google with your production domains
- For production, use a managed PostgreSQL service with connection pooling