Deploy to Vercel
Production deployment with automatic scaling and preview environments
Vercel provides native Next.js 15 support with automatic edge optimization, preview deployments on every PR, and zero-downtime production rollouts.
Pro Tip
Vercel auto-detects monorepos. Create separate projects for apps/marketing
and apps/dashboard
with Turbo build commands.
Prerequisites
GitHub Repository
Push your StarterApp to GitHub. Vercel integrates via OAuth, detecting monorepo structure automatically.
Vercel Account
Sign up at vercel.com. The free Hobby tier supports:
- Unlimited deployments
- 100GB bandwidth/month
- Automatic HTTPS
- Global CDN distribution
Environment Variables Ready
Prepare production values for authentication, database, and billing credentials.
Deployment Walkthrough
Import Repository
Navigate to vercel.com/new and select Import Git Repository.
Monorepo Detection
Vercel auto-detects monorepos. You'll need to create separate projects for apps/marketing
and apps/dashboard
.
Click Select on your GitHub repository.
Configure Build Settings
# Framework Preset
Next.js
# Root Directory
apps/marketing
# Build Command (override default)
cd ../.. && pnpm turbo run build --filter=marketing
# Install Command (override default)
pnpm install --frozen-lockfile --prod=false
# Output Directory
.next (auto-detected)
# Node.js Version
20.x (from .nvmrc)
Why --prod=false?
Vercel runs builds with NODE_ENV=production
. The --prod=false
flag ensures devDependencies like TypeScript, Tailwind CSS, and Turbo remain available during compilation.
# Framework Preset
Next.js
# Root Directory
apps/dashboard
# Build Command (override default)
cd ../.. && pnpm turbo run build --filter=dashboard
# Install Command (override default)
pnpm install --frozen-lockfile --prod=false
# Output Directory
.next (auto-detected)
# Node.js Version
20.x (from .nvmrc)
Set Environment Variables
In Configure Project → Environment Variables, add:
# Core Application (update after first deploy)
APP_BASE_URL=https://your-production-domain.com
DASHBOARD_BASE_URL=https://dashboard.your-domain.com
NEXT_PUBLIC_DASHBOARD_BASE_URL=https://dashboard.your-domain.com
# Authentication
BETTER_AUTH_SECRET=<generate: openssl rand -base64 32>
GOOGLE_CLIENT_ID=<from Google Cloud Console>
GOOGLE_CLIENT_SECRET=<from Google Cloud Console>
# Database
NEXT_PUBLIC_CONVEX_URL=https://your-prod.convex.cloud
CONVEX_DEPLOYMENT=production
# Billing
AUTUMN_SECRET_KEY=am_sk_live_<your-production-key>
# Security
ALLOWED_WEB_ORIGINS=https://your-domain.com,https://www.your-domain.com
ENABLE_HSTS=1
HSTS_PRELOAD=0
# Analytics (optional)
NEXT_PUBLIC_POSTHOG_KEY=phc_<your-key>
NEXT_PUBLIC_POSTHOG_HOST=https://app.posthog.com
# Use staging/preview credentials
APP_BASE_URL=https://preview-<branch>-<project>.vercel.app
NEXT_PUBLIC_CONVEX_URL=https://your-preview.convex.cloud
CONVEX_DEPLOYMENT=preview
# Same auth secret, different OAuth callbacks
BETTER_AUTH_SECRET=<same-as-production>
# Test billing key
AUTUMN_SECRET_KEY=am_sk_test_<your-test-key>
# Relaxed security for previews
ENABLE_HSTS=0
HSTS_PRELOAD=0
# Local development values
APP_BASE_URL=http://localhost:3000
DASHBOARD_BASE_URL=http://localhost:3001
NEXT_PUBLIC_CONVEX_URL=https://your-dev.convex.cloud
# Development mode disables certain security headers
ENABLE_HSTS=0
Environment Scope
Select appropriate scopes:
- Production: Only main branch deploys
- Preview: All branch deploys
- Development: Local
vercel dev
command
Deploy
Click Deploy to trigger the initial build. Vercel will:
- Clone repository
- Install dependencies via pnpm
- Run Turbo build with caching
- Deploy to global edge network
- Provision SSL certificate
- Assign production URL
Initial deploy time: ~3-5 minutes Subsequent deploys: ~1-2 minutes (with Turbo cache)
Update Environment URLs
After deployment completes, Vercel assigns a URL:
https://<project-name>.vercel.app
Navigate to Settings → Environment Variables and update:
APP_BASE_URL=https://<project-name>.vercel.app
ALLOWED_WEB_ORIGINS=https://<project-name>.vercel.app
Trigger a redeploy via Deployments → ••• → Redeploy.
Sync Convex Environment
Mirror credentials to Convex so BetterAuth and UseAutumn run in the hosted runtime:
# Set production deployment
npx convex deploy --prod
# Configure environment variables
npx convex env set APP_BASE_URL https://<project-name>.vercel.app --prod
npx convex env set DASHBOARD_BASE_URL https://dashboard-<project>.vercel.app --prod
npx convex env set ALLOWED_WEB_ORIGINS https://<project-name>.vercel.app --prod
npx convex env set BETTER_AUTH_SECRET <same-value-as-vercel> --prod
npx convex env set GOOGLE_CLIENT_ID <same-value-as-vercel> --prod
npx convex env set GOOGLE_CLIENT_SECRET <same-value-as-vercel> --prod
npx convex env set AUTUMN_SECRET_KEY <same-value-as-vercel> --prod
Environment Parity Critical
Mismatched environment variables between Vercel and Convex cause authentication failures and billing errors.
Custom Domain Setup
Add Domain in Vercel
Navigate to Settings → Domains and add your custom domain:
your-domain.com
www.your-domain.com
Vercel provides DNS configuration instructions.
Configure DNS
Add records at your DNS provider:
Type: A
Name: @
Value: 76.76.21.21
TTL: 3600
For www
subdomain:
Type: CNAME
Name: www
Value: cname.vercel-dns.com
TTL: 3600
For subdomains (dashboard, app, etc.):
Type: CNAME
Name: dashboard
Value: cname.vercel-dns.com
TTL: 3600
Update Environment Variables
After domain verification, update all environment URLs:
APP_BASE_URL=https://your-domain.com
DASHBOARD_BASE_URL=https://dashboard.your-domain.com
ALLOWED_WEB_ORIGINS=https://your-domain.com,https://www.your-domain.com
Update OAuth callbacks with new domain and redeploy.
Preview Deployments
Every pull request receives an automatic preview deployment.
Pro Tip
Preview URLs follow the pattern: https://<project>-git-<branch>-<team>.vercel.app
Preview Configuration
// vercel.json (optional)
{
"git": {
"deploymentEnabled": {
"main": true,
"staging": true
}
},
"github": {
"autoAlias": true,
"silent": false
}
}
Preview Environment Variables
Previews inherit environment variables based on scope. Override preview-specific values in Settings → Environment Variables → Preview.
Performance Optimization
Vercel Edge Runtime provides global distribution with minimal latency:
// app/api/auth/[...all]/route.ts
export const runtime = 'edge'; // Deploy to 100+ global regions
export const preferredRegion = 'auto'; // Closest to user
Compatible with:
- Authentication routes (BetterAuth)
- API endpoints (server actions via edge compatibility)
- Middleware
Not compatible with:
- Node.js-specific APIs (fs, child_process)
- Large dependencies (>1MB after minification)
Vercel automatically optimizes images via Next.js Image component:
import Image from 'next/image';
<Image
src="/hero.jpg"
alt="Hero image"
width={1200}
height={630}
priority // LCP optimization
/>
Benefits:
- Automatic WebP/AVIF conversion
- Responsive srcset generation
- Lazy loading by default
- CDN caching
Configure caching headers for optimal performance:
// next.config.ts
export default {
async headers() {
return [
{
source: '/api/public/:path*',
headers: [
{
key: 'Cache-Control',
value: 'public, s-maxage=3600, stale-while-revalidate=86400'
}
]
}
];
}
};
Vercel respects Cache-Control
headers for edge caching.
Monitoring and Analytics
Troubleshooting
Advanced Configuration
{
"buildCommand": "pnpm turbo run build --filter=marketing",
"installCommand": "pnpm install --frozen-lockfile --prod=false",
"framework": "nextjs",
"regions": ["iad1"],
"env": {
"APP_NAME": "StarterApp"
}
}
// next.config.ts
export default {
async redirects() {
return [
{
source: '/old-path',
destination: '/new-path',
permanent: true
}
];
}
};
Security headers are configured in middleware.ts
but can be supplemented:
// next.config.ts
export default {
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'X-Frame-Options',
value: 'DENY'
}
]
}
];
}
};