Skip to main content

Deployment Guide

Choose the deployment method that best fits your needs.


Deployment Options

MethodDifficultyCostBest For
Vercel⭐ EasyFree - $20/moQuick launch, no DevOps
Docker⭐⭐⭐ Advanced~$6/mo VPSFull control, consistent env
PM2⭐⭐ Medium~$6/mo VPSSimple VPS, no containers

Quick Comparison

Setup Time

Vercel:  ████░░░░░░  ~5 minutes
PM2: ██████░░░░ ~30 minutes
Docker: ████████░░ ~1 hour

Control vs Convenience

                    More Control


Docker ────┼──── More Work

PM2 ─────┤

Vercel ─────┼──── Less Work


More Convenient

Decision Guide

Choose Vercel if:

  • ✅ You want the fastest deployment
  • ✅ You don't want to manage servers
  • ✅ Your app fits within serverless constraints
  • ✅ You need automatic scaling
  • ✅ Preview deployments are important

Choose Docker if:

  • ✅ You need full control over infrastructure
  • ✅ You want consistent environments (dev = prod)
  • ✅ You plan to scale to multiple servers
  • ✅ You need custom server configuration
  • ✅ You want to avoid vendor lock-in

Choose PM2 if:

  • ✅ You have a simple VPS
  • ✅ You don't need containerization
  • ✅ You want minimal overhead
  • ✅ You're comfortable with Node.js
  • ✅ You want easy debugging

External Services (All Methods)

Regardless of deployment method, you'll need:

ServicePurposeFree Tier
NeonPostgreSQL✅ Generous
UpstashRedis✅ 10K commands/day
StripePaymentsPay per transaction
ResendEmail✅ 100 emails/day
CloudinaryImages✅ 25K transformations
Google CloudOAuth✅ Free

Environment Variables

All deployment methods require these environment variables:

# Database
DATABASE_URL="postgresql://..."

# Auth
AUTH_SECRET="..."
NEXTAUTH_URL="https://yourdomain.com"

# Stripe
STRIPE_SECRET_KEY="sk_..."
STRIPE_WEBHOOK_SECRET="whsec_..."
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_..."

# Redis
UPSTASH_REDIS_REST_URL="https://..."
UPSTASH_REDIS_REST_TOKEN="..."

# OAuth
GOOGLE_CLIENT_ID="..."
GOOGLE_CLIENT_SECRET="..."

# Email
RESEND_API_KEY="re_..."

# Images
CLOUDINARY_CLOUD_NAME="..."
CLOUDINARY_API_KEY="..."
CLOUDINARY_API_SECRET="..."

Post-Deployment Checklist

  • Site loads over HTTPS
  • User registration works
  • Google OAuth works
  • Test checkout completes (use 4242 4242 4242 4242)
  • Webhook receives events (check Stripe dashboard)
  • Admin panel accessible
  • Emails sending correctly
  • Images loading from Cloudinary

Stripe Webhook Setup

After deployment, configure Stripe webhook:

  1. Go to Stripe Dashboard
  2. Click "Add endpoint"
  3. Enter URL: https://yourdomain.com/api/webhooks/stripe
  4. Select events:
    • checkout.session.completed
    • checkout.session.expired
  5. Copy webhook signing secret to your environment variables

Google OAuth Setup

  1. Go to Google Cloud Console
  2. Create or select a project
  3. Enable "Google+ API"
  4. Go to Credentials → Create OAuth Client ID
  5. Add authorized redirect URI:
    • https://yourdomain.com/api/auth/callback/google
  6. Copy Client ID and Secret to environment variables

Troubleshooting

Common Issues

IssueCauseSolution
500 errorsMissing env varsCheck all variables are set
OAuth failsWrong redirect URIUpdate Google Console
Payments failWrong webhook URLUpdate Stripe Dashboard
Images brokenCloudinary not configuredCheck cloud name
Auth loopsNEXTAUTH_URL mismatchMatch your actual domain

Debug Checklist

# 1. Check environment variables are loaded
# 2. Check database connection
# 3. Check Redis connection
# 4. Check Stripe webhook logs
# 5. Check application logs