Vercel Deployment Guide

Complete checklist for deploying Raypx to Vercel with database, Redis, Stripe, and email services configuration

Project: Raypx - TanStack Start + React 19 + PostgreSQL + Redis + Stripe Platform: Vercel Created: 2025-01-19

Pre-Deployment Preparation (Local Verification)

✅ 1. Local Build Test

# Clean cache
pnpm clean

# Install dependencies
pnpm install

# Type check
pnpm typecheck

# Code check
pnpm check

# Full build
pnpm build

# Verify build output
ls -la apps/web/dist/client
ls -la apps/web/dist/server

✅ Validation Standards:

  • TypeScript: No errors
  • Biome: No warnings
  • Build: Success (exit code 0)
  • Dist: Client and server files exist

✅ 2. Environment Variables Preparation

Create .env.production file (do NOT commit to git), prepare the following variables:

# Copy template
cp .env.example .env.production

# Edit production environment variables
# Below is the list of required variables

🗄️ Database Setup (Choose 1 of 3)

Advantages: Large free tier, Serverless, Auto-scaling

Steps:

  1. Visit https://neon.tech
  2. Create new project → Select region (suggest us-east-1 near Vercel)
  3. Get connection string:
    DATABASE_URL=postgresql://user:pass@ep-xxx.us-east-1.aws.neon.tech/raypx?sslmode=require
  4. Run database migrations:
    DATABASE_URL="postgresql://..." pnpm --filter @raypx/db run db:migrate
  5. Verify database:
    DATABASE_URL="postgresql://..." pnpm --filter @raypx/db run db:studio

Option 2: Vercel Postgres (Easiest)

Advantages: Native Vercel integration, One-click connection

Steps:

  1. Vercel Dashboard → Storage → Create Database → Postgres
  2. Select project association
  3. Auto-inject environment variable POSTGRES_URL
  4. Modify packages/db/src/envs.ts:
    DATABASE_URL: z.string().url().default(process.env.POSTGRES_URL || '')
  5. Run migrations locally (connecting to Vercel Postgres):
    vercel env pull .env.local
    pnpm --filter @raypx/db run db:migrate

Option 3: Any Standard PostgreSQL

Advantages: Most flexible, works with any PostgreSQL provider

Steps:

  1. Use any PostgreSQL hosting service (Railway, Render, DigitalOcean, etc.)
  2. Get connection string:
    DATABASE_URL=postgresql://user:pass@host:5432/raypx?sslmode=require
  3. Run migrations (same as Neon)

✅ Verify Database Connection:

# Test connection
DATABASE_URL="postgresql://..." psql -c "SELECT version();"

# View tables
DATABASE_URL="postgresql://..." pnpm --filter @raypx/db run db:studio

🔴 Redis Setup (Choose 1 of 2)

Steps:

  1. Vercel Dashboard → Storage → Create Database → KV
  2. Select project association
  3. Auto-inject environment variables KV_REST_API_URL and KV_REST_API_TOKEN
  4. Modify packages/redis/src/envs.ts:
    REDIS_URL: z.string().url().optional(),
    KV_REST_API_URL: z.string().url().optional(),
    KV_REST_API_TOKEN: z.string().optional(),

Option 2: Upstash Redis

Steps:

  1. Visit https://upstash.com
  2. Create Redis Database
  3. Select region (suggest us-east-1)
  4. Get REST API URL and Token:
    REDIS_URL=https://xxx.upstash.io
    UPSTASH_REDIS_REST_TOKEN=AXXXxxx

⚠️ Note: Redis is optional. If not configured, caching will fallback to in-memory cache

✅ Verify Redis Connection:

# Test with redis-cli
redis-cli -u "redis://default:password@host:port"
PING

💳 Stripe Configuration

1. Get API Keys

Production Keys (Dashboard → Developers → API keys):

STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxxx
STRIPE_PUBLISHABLE_KEY=pk_live_xxxxxxxxxxxxx

⚠️ Test Keys (Verify with test environment first):

STRIPE_SECRET_KEY=sk_test_xxxxxxxxxxxxx
STRIPE_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxx

2. Configure Webhook

Steps:

  1. Stripe Dashboard → Developers → Webhooks

  2. Add endpoint:

    URL: https://yourdomain.com/api/billing/webhook
  3. Select events to listen:

    • checkout.session.completed
    • customer.subscription.created
    • customer.subscription.updated
    • customer.subscription.deleted
    • invoice.paid
    • invoice.payment_failed
    • payment_method.attached
    • checkout.session.async_payment_succeeded
    • checkout.session.async_payment_failed
  4. Get Webhook signing secret:

    STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxx

✅ Test Webhook (Local):

# Install Stripe CLI
stripe listen --forward-to localhost:3000/api/billing/webhook

# Trigger test event
stripe trigger checkout.session.completed

📧 Email Service Configuration (Resend)

1. Get API Key

Steps:

  1. Visit https://resend.com
  2. API Keys → Create API Key
  3. Configure:
    RESEND_API_KEY=re_xxxxxxxxxxxxx
    RESEND_FROM=noreply@yourdomain.com

2. Verify Domain (Required for Production)

Steps:

  1. Resend → Domains → Add Domain
  2. Add DNS records:
    Type: TXT
    Name: _resend
    Value: (Value provided by Resend)
  3. Wait for verification (about 5-10 minutes)

⚠️ Testing Phase: You can use Resend's test domain onboarding@resend.dev

✅ Test Email Sending:

# Start email preview service
pnpm email:dev

# Visit http://localhost:3003
# Test sending emails

🔐 Authentication Configuration (Better Auth)

Required Variables

# Better Auth secret (generate: openssl rand -base64 32)
AUTH_SECRET=your-super-secret-key-min-32-characters

# Better Auth URL (production domain)
BETTER_AUTH_URL=https://yourdomain.com

# OAuth providers (optional)
AUTH_GITHUB_ID=your_github_client_id
AUTH_GITHUB_SECRET=your_github_client_secret

AUTH_GOOGLE_ID=your_google_client_id.apps.googleusercontent.com
AUTH_GOOGLE_SECRET=your_google_client_secret

GitHub OAuth Configuration (Optional)

Steps:

  1. GitHub Settings → Developer settings → OAuth Apps → New OAuth App
  2. Configure:
    Application name: Raypx
    Homepage URL: https://yourdomain.com
    Authorization callback URL: https://yourdomain.com/api/auth/callback/github
  3. Get Client ID and Secret

Google OAuth Configuration (Optional)

Steps:

  1. Google Cloud Console → APIs & Services → Credentials
  2. Create OAuth 2.0 Client ID
  3. Configure:
    Authorized redirect URIs:
    https://yourdomain.com/api/auth/callback/google

🚀 Vercel Deployment Steps

1. Connect GitHub Repository

Steps:

  1. Visit https://vercel.com
  2. Import Project → Select GitHub repository
  3. Configure Project:
    Framework Preset: Other
    Root Directory: ./
    Build Command: pnpm build
    Output Directory: apps/web/dist
    Install Command: pnpm install

2. Configure Environment Variables

Vercel Dashboard → Settings → Environment Variables

Required Variables (Production):

# === App Configuration ===
NODE_ENV=production
VITE_SITE_URL=https://yourdomain.com
VITE_WEB_URL=https://yourdomain.com

# === Database ===
DATABASE_URL=postgresql://user:pass@host:5432/raypx

# === Redis (optional) ===
REDIS_URL=redis://default:pass@host:6379
# Or use Vercel KV (auto-injected)

# === Better Auth ===
AUTH_SECRET=your-super-secret-key-min-32-characters
BETTER_AUTH_URL=https://yourdomain.com

# === Stripe ===
STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxxx
VITE_STRIPE_PUBLISHABLE_KEY=pk_live_xxxxxxxxxxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxx

# === Email (Resend) ===
RESEND_API_KEY=re_xxxxxxxxxxxxx
RESEND_FROM=noreply@yourdomain.com
AUTH_RESEND_KEY=re_xxxxxxxxxxxxx

# === Analytics (optional) ===
VITE_SENTRY_DSN=https://xxx@sentry.io/xxx
VITE_PUBLIC_POSTHOG_KEY=phc_xxxxxxxxxxxxx
VITE_PUBLIC_POSTHOG_HOST=https://app.posthog.com

⚠️ Environment Variable Notes:

  • VITE_ prefix variables are exposed to the client
  • Sensitive keys (SECRET, API_KEY) should NOT use VITE_ prefix
  • Ensure all variables are set to Production environment

3. Trigger Deployment

# Method 1: GitHub push
git add .
git commit -m "chore: prepare for deployment"
git push origin main

# Method 2: Use Vercel CLI
pnpm add -g vercel
vercel --prod

# Method 3: Vercel Dashboard manual trigger
# Deployments → Redeploy

4. Post-Deployment Verification

✅ Checklist:

  • Visit https://yourdomain.com to confirm homepage loads
  • Test user registration (email verification sent)
  • Test login/logout
  • Test user profile update
  • Test Stripe payment flow
  • Check Vercel logs for errors
  • Verify database writes data correctly

View Logs:

# Vercel CLI real-time logs
vercel logs

# Or visit Vercel Dashboard → Deployments → Click deployment → Logs

🌍 Domain Configuration

1. Add Custom Domain

Steps:

  1. Vercel Dashboard → Settings → Domains
  2. Add Domain → Enter yourdomain.com
  3. Configure DNS:

Option 1: Use Vercel DNS (Recommended)

Change domain registrar's Nameservers:
ns1.vercel-dns.com
ns2.vercel-dns.com

Option 2: Use CNAME

Type: CNAME
Name: www
Value: cname.vercel-dns.com

Option 3: Use A Record

Type: A
Name: @
Value: 76.76.21.21

2. SSL Certificate

Vercel Auto-Configuration:

  • Automatically issues Let's Encrypt certificate
  • Auto-renewal
  • Force HTTPS redirect

✅ Verify SSL:

curl -I https://yourdomain.com
# Check response headers for "strict-transport-security"

🔧 Build Optimization Configuration

1. vercel.json Configuration (Optional)

{
  "buildCommand": "pnpm build",
  "outputDirectory": "apps/web/dist",
  "devCommand": "pnpm dev",
  "installCommand": "pnpm install",
  "framework": null,
  "regions": ["iad1"],
  "functions": {
    "apps/web/dist/server/**": {
      "maxDuration": 30
    }
  },
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "X-Content-Type-Options",
          "value": "nosniff"
        },
        {
          "key": "X-Frame-Options",
          "value": "DENY"
        },
        {
          "key": "X-XSS-Protection",
          "value": "1; mode=block"
        }
      ]
    }
  ]
}

2. Performance Optimization

package.json scripts:

{
  "scripts": {
    "vercel-build": "pnpm build"
  }
}

Cache Optimization:

  • Vercel automatically caches node_modules
  • Use pnpm for faster dependency installation
  • Turborepo caches build artifacts

🐛 Common Issues Troubleshooting

Issue 1: Build Failure - "Cannot find module"

Cause: pnpm workspace dependencies not resolved correctly

Solution:

# Ensure .npmrc exists
shamefully-hoist=true

# Clean and reinstall
rm -rf node_modules pnpm-lock.yaml
pnpm install

Issue 2: Environment Variables Not Working

Cause: Environment variable scope error

Solution:

  1. Check Vercel environment variables set to Production
  2. Redeploy to trigger environment variable update
  3. Confirm VITE_ prefix variables injected at build time

Issue 3: Database Connection Failed

Cause: SSL connection issue or IP whitelist

Solution:

# Add SSL parameter to database URL
DATABASE_URL=postgresql://...?sslmode=require

# Neon/Supabase: Add Vercel IP to whitelist
# Or use "Allow all IPs" (not recommended for production)

Issue 4: Stripe Webhook Not Working

Cause: Webhook signature verification failed

Solution:

  1. Confirm STRIPE_WEBHOOK_SECRET is correct
  2. Check Stripe Dashboard webhook endpoint URL
  3. View Vercel Function logs:
    vercel logs --follow

Issue 5: Email Sending Failed

Cause: Resend domain not verified or API key error

Solution:

  1. Check Resend domain DNS configuration
  2. Use onboarding@resend.dev for testing
  3. Verify RESEND_API_KEY is correct

📊 Post-Deployment Monitoring

1. Log Monitoring

# Real-time logs
vercel logs --follow

# Filter error logs
vercel logs --follow | grep ERROR

2. Performance Monitoring

Vercel Analytics (Free):

  1. Vercel Dashboard → Analytics
  2. View:
    • Requests per second
    • Response time
    • Error rate
    • Geographic distribution

Sentry Error Monitoring (Recommended):

VITE_SENTRY_DSN=https://xxx@sentry.io/xxx

3. Database Monitoring

Neon Dashboard:

  • Query performance
  • Connection count
  • Storage usage

Drizzle Studio (Local):

DATABASE_URL="postgresql://..." pnpm --filter @raypx/db run db:studio

✅ Final Checklist

Pre-Deployment (Local)

  • pnpm typecheck passes
  • pnpm check passes
  • pnpm build succeeds
  • All TODO code completed or commented
  • .env.example updated

Vercel Configuration

  • GitHub repository connected
  • Build command configured correctly
  • Production environment variables set
  • Database created and migrated
  • Redis configured (optional)

External Services

  • Stripe API keys configured
  • Stripe Webhook created
  • Resend API key configured
  • Resend domain verified (production)
  • GitHub/Google OAuth configured (optional)

Post-Deployment Verification

  • Homepage loads normally
  • User registration/login works
  • Email sending works
  • Payment flow works
  • Webhook receiving works
  • No critical errors in logs

Domain and SSL

  • Custom domain added
  • DNS configured
  • SSL certificate active
  • HTTPS forced redirect

🚀 Quick Deployment Commands

# 1. Local verification
pnpm clean && pnpm install && pnpm build

# 2. Commit code
git add .
git commit -m "chore: prepare for deployment"
git push origin main

# 3. Deploy with Vercel CLI (optional)
vercel --prod

# 4. Verify deployment
curl -I https://yourdomain.com
vercel logs --follow

📚 Reference Resources


Created: 2025-01-19 Last Updated: 2025-01-19 Maintained By: Raypx Team

Edit on GitHub

Last updated on