Deploy to Vercel
Deploy ProductReady to production in 5 minutes with Vercel's one-click deployment
Deploy to Vercel
Vercel is the fastest and easiest way to deploy ProductReady to production. This guide walks you through the entire process.
Why Vercel?
- Zero configuration needed
- Automatic HTTPS and CDN
- Free tier includes hobby projects
- Deploy on every git push
- Built by the creators of Next.js
Prerequisites
Before deploying, you need:
- ✅ GitHub account (to connect your repo)
- ✅ Vercel account (sign up free)
- ✅ Database (Neon, Supabase, or other PostgreSQL)
- ✅ Environment variables ready (see below)
Quick Deploy (5 Minutes)
Push your code to GitHub
# Initialize git (if not already)
git init
git add .
git commit -m "Initial commit"
# Create repo on GitHub, then:
git remote add origin https://github.com/YOUR-USERNAME/YOUR-REPO.git
git push -u origin mainConnect to Vercel
- Go to vercel.com/new
- Click "Import Git Repository"
- Select your ProductReady repository
- Click "Import"
First time? Vercel will ask to install the GitHub App - click "Install"
Configure project
Vercel auto-detects Next.js. Verify these settings:
- Framework Preset: Next.js
- Root Directory:
apps/productready(if in monorepo) or./(if standalone) - Build Command:
pnpm build(ornpm run build) - Output Directory:
.next(auto-detected)
Click "Deploy" - don't worry, it will fail first time (we need env vars!)
Add environment variables
After first deploy fails, go to: Project Settings → Environment Variables
Add these required variables:
# Database
PG_DATABASE_URL=postgresql://user:pass@host:5432/db
# Auth
BETTER_AUTH_SECRET=your-secret-32-chars-minimum
BETTER_AUTH_URL=https://your-app.vercel.app
# Optional: OAuth
GITHUB_CLIENT_ID=your-github-oauth-id
GITHUB_CLIENT_SECRET=your-github-oauth-secret
GOOGLE_CLIENT_ID=your-google-oauth-id
GOOGLE_CLIENT_SECRET=your-google-oauth-secretImportant: Update BETTER_AUTH_URL to your actual Vercel domain!
Redeploy
Click "Deployments" tab → Find latest deploy → Click "⋯" → "Redeploy"
Or just push a new commit:
git commit --allow-empty -m "Trigger deploy"
git pushThis time it will succeed! 🎉
Run database migrations
After successful deploy, run migrations:
Option 1: Use Vercel CLI
# Install Vercel CLI
npm install -g vercel
# Login
vercel login
# Run migration
vercel env pull .env.production
pnpm db:migrateOption 2: Connect to your database directly
# Set PG_DATABASE_URL from Vercel
export PG_DATABASE_URL="your-production-db-url"
# Run migrations
pnpm db:migrate
# Seed data (optional)
pnpm db:seedTest your app
Visit your Vercel URL (e.g., https://your-app.vercel.app)
Test:
- ✅ Landing page loads
- ✅ Sign up / Login works
- ✅ Dashboard accessible
- ✅ Health check:
https://your-app.vercel.app/api/health
Deployed! Every git push to main will now automatically deploy to production.
Environment Variables Explained
Required Variables
PG_DATABASE_URL
Your PostgreSQL connection string.
Format: postgresql://user:password@host:port/database
Where to get it:
- Neon: Dashboard → Connection Details → Connection string
- Supabase: Project Settings → Database → Connection string (use "Connection pooling")
- Railway: Database → Connect → Postgres Connection URL
Use connection pooling for serverless (Vercel). Most providers offer pooled connections on a different port (usually 6543 instead of 5432).
BETTER_AUTH_SECRET
Secret key for signing sessions/tokens.
Generate:
openssl rand -base64 32Copy the output and paste as BETTER_AUTH_SECRET.
Important: Use different secrets for dev and production!
BETTER_AUTH_URL
The public URL where your app is hosted.
- Development:
http://localhost:3000 - Production:
https://your-app.vercel.app(or your custom domain)
Custom domain? Update this after adding your domain in Vercel settings.
Optional Variables (OAuth)
GitHub OAuth
- Go to GitHub Developer Settings
- Click "New OAuth App"
- Fill in:
- Application name: Your App Name
- Homepage URL:
https://your-app.vercel.app - Authorization callback URL:
https://your-app.vercel.app/api/auth/callback/github
- Click "Register application"
- Copy Client ID and Client Secret
Add to Vercel:
GITHUB_CLIENT_ID=your_client_id
GITHUB_CLIENT_SECRET=your_client_secretGoogle OAuth
- Go to Google Cloud Console
- Create project → Enable "Google+ API"
- Create OAuth 2.0 credentials
- Add authorized redirect URI:
https://your-app.vercel.app/api/auth/callback/google - Copy Client ID and Client Secret
Add to Vercel:
GOOGLE_CLIENT_ID=your_client_id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your_client_secretCustom Domain
Add your domain
Buy a domain
Buy from: Namecheap, GoDaddy, Cloudflare, or any registrar.
Add to Vercel
- Go to Project Settings → Domains
- Enter your domain (e.g.,
myapp.com) - Click "Add"
Update DNS
Vercel shows DNS records to add. Go to your domain registrar and add:
For root domain (myapp.com):
Type: A
Name: @
Value: 76.76.21.21For www subdomain:
Type: CNAME
Name: www
Value: cname.vercel-dns.comWait for DNS propagation
Usually takes 5-30 minutes. Vercel will show "Valid Configuration" when ready.
Update environment variables
Update BETTER_AUTH_URL to use your custom domain:
BETTER_AUTH_URL=https://myapp.comRedeploy for changes to take effect.
Monitoring & Analytics
View logs
Vercel Dashboard → Deployments → Click deployment → View Function Logs
You'll see:
- API requests
- Errors and stack traces
- Console.log output
- Performance metrics
Health check
ProductReady includes a health endpoint:
curl https://your-app.vercel.app/api/healthResponse:
{
"status": "healthy",
"timestamp": "2024-03-15T10:30:00.000Z",
"version": "1.0.0",
"buildNumber": 42,
"commit": "abc1234"
}Use this for:
- Uptime monitoring (UptimeRobot, Pingdom)
- Health checks in load balancers
- Deployment verification
Analytics
Option 1: Vercel Analytics (built-in)
- Go to Project → Analytics
- Enable Vercel Analytics
- Add package:
pnpm add @vercel/analytics - Add to
src/app/layout.tsx:import { Analytics } from '@vercel/analytics/react'; export default function RootLayout({ children }) { return ( <html> <body> {children} <Analytics /> </body> </html> ); }
Option 2: Google Analytics Use env vars and add GA script to layout.
Performance Optimization
Enable caching
Add to next.config.mjs:
/** @type {import('next').NextConfig} */
const nextConfig = {
// Cache static pages for 1 year
async headers() {
return [
{
source: '/assets/:path*',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable',
},
],
},
];
},
};
export default nextConfig;Image optimization
Use Next.js <Image> component:
import Image from 'next/image';
<Image
src="/logo.png"
alt="Logo"
width={200}
height={50}
priority // for above-fold images
/>Database connection pooling
Critical for Vercel! Use connection pooling to avoid exhausting database connections.
Neon/Supabase provide this automatically. If self-hosting, use PgBouncer.
CI/CD with GitHub Actions
Want more control? Use GitHub Actions before deploying to Vercel.
Create .github/workflows/ci.yml:
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
version: 9
- uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'pnpm'
- run: pnpm install
- run: pnpm lint
- run: pnpm test
- run: pnpm buildThis runs on every push and blocks merge if tests fail.
Troubleshooting
"Build failed: Module not found"
Solution: Ensure dependencies are in package.json, not just installed locally.
# Re-install to update lock file
pnpm install
# Commit changes
git add package.json pnpm-lock.yaml
git commit -m "Update dependencies"
git push"Database connection failed"
Check:
- Is
PG_DATABASE_URLset in Vercel env vars? - Is connection string correct? (Copy-paste carefully!)
- Is database accepting external connections?
- Using connection pooling? (Neon port 5432 → 6543)
"OAuth not working"
Check:
- OAuth callback URLs match your domain exactly
BETTER_AUTH_URLis set to production URL (not localhost!)- OAuth client secrets are correct
- Redeploy after changing env vars
"Deployment successful but site is blank"
Check browser console for errors.
Common issues:
- Missing env vars → Functions fail silently
- Database not migrated → API calls fail
- CORS issues → Check
BETTER_AUTH_URL
"Too many database connections"
Solution: Use connection pooling!
Neon example (note port 6543):
postgresql://user:pass@host:6543/db?sslmode=requireOr use Drizzle with pool:
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
const client = postgres(process.env.PG_DATABASE_URL!, {
max: 10, // Connection pool size
});
export const db = drizzle(client);Production Checklist
Before going live:
- All env vars set (especially
BETTER_AUTH_SECRET,PG_DATABASE_URL) - Database migrated (
pnpm db:migrate) - Health check works (
/api/healthreturns 200) - OAuth configured (GitHub/Google redirect URIs)
- Custom domain added (if applicable)
-
BETTER_AUTH_URLupdated to production URL - Analytics enabled (Vercel or Google)
- Error monitoring setup (Sentry optional)
- Test signup/login flow
- Test all main features
- Check mobile responsiveness
- Review security (no secrets in frontend code!)
Next Steps
- Configure database backups
- Set up error monitoring with Sentry
- Docker deployment (self-hosted)
- Environment best practices
🎉 Congrats on deploying to production! Now ship features, not infrastructure.