Skip to main content
Vercel is the recommended hosting platform for Sabo. This guide covers importing your project, configuring environment variables, setting up production webhooks, and verifying your deployment works correctly.

Prerequisites

Before deploying, ensure you have:
  • Vercel account (Sign up free)
  • Git repository (GitHub, GitLab, or Bitbucket) with your Sabo project pushed
  • Supabase project configured with database migration applied (Database with Supabase)
  • Local environment working (pnpm dev runs successfully with all features)
  • Stripe account configured for payments (Setup guide)
  • PostHog account for analytics (Setup guide)
  • Custom domain (can be added after initial deployment)
Local build test: Run pnpm build locally to catch any build errors before deploying.

Step-by-Step Deployment

1

Import project to Vercel

Connect your repository to Vercel:
  1. Go to Vercel Dashboard
  2. Click Add New…Project
  3. Select your Git provider and authorize access
  4. Choose your Sabo repository from the list
  5. Vercel will auto-detect Next.js settings:
    • Framework Preset: Next.js
    • Root Directory: ./ (or ./sabo if using a monorepo)
    • Build Command: pnpm run build (runs the build script which calls next build)
    • Output Directory: .next (auto-detected)
    • Install Command: pnpm install (auto-detected from pnpm-lock.yaml)
Sabo uses Next.js 16 with App Router. Vercel automatically detects the correct build configuration. No manual settings needed.
Project imported successfully. You should see the “Configure Project” screen.
2

Configure environment variables

Add all required environment variables in the Vercel project configuration screen. Click Environment Variables and add each variable below.

Core Variables (Required)

# Site URL
NEXT_PUBLIC_SITE_URL=https://your-project.vercel.app

# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=eyJhbGciOiJIUzI1N...
SUPABASE_SECRET_KEY=sbp_1234567890abcdef...
For production, set NEXT_PUBLIC_SITE_URL to your actual domain, not the .vercel.app URL. Update this after adding a custom domain.

Stripe Variables (Required for payments)

# Stripe API Keys
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...

# Stripe Product Price IDs (optional, for pricing page)
NEXT_PUBLIC_STRIPE_PRICE_ID_PRO_MONTHLY=price_...
NEXT_PUBLIC_STRIPE_PRICE_ID_PRO_YEARLY=price_...

# Stripe Customer Portal Configuration (optional)
STRIPE_CUSTOMER_PORTAL_CONFIG_ID=bpc_...
Test mode vs. Production:
  • For Production environment: Use sk_live_... and pk_live_...
  • For Preview environment: You can use sk_test_... and pk_test_...
Set environment variable scopes in Vercel to control which keys are used in which environments.

PostHog Variables (Optional, for analytics)

NEXT_PUBLIC_POSTHOG_KEY=phc_...
NEXT_PUBLIC_POSTHOG_HOST=https://app.posthog.com
PostHog is optional. Sabo only activates analytics if these variables are set.

Testing Variables (Optional, for E2E tests)

TEST_USER_EMAIL=[email protected]
TEST_USER_PASSWORD=secure_test_password
Only needed if running Playwright tests in CI/CD (e.g., GitHub Actions). Not required for deployment.

Environment Variable Scopes

For each variable, select the appropriate scope:
  • Production - Live site environment
  • Preview - Pull request and branch preview deployments
  • Development - Local development (usually not needed; use .env.local)
Use Production scope for all variables initially. You can refine scopes later (e.g., test Stripe keys for Preview, live keys for Production).
All environment variables added and saved in Vercel.
3

Update Supabase Auth URLs

Configure Supabase to allow authentication from your Vercel domain:
  1. Go to Supabase Dashboard → Your Project
  2. Navigate to AuthenticationURL Configuration
  3. Update Site URL to:
    https://your-project.vercel.app
    
    (or your custom domain: https://yourdomain.com)
  4. Add to Redirect URLs (comma-separated list):
    https://your-project.vercel.app/auth/callback
    https://yourdomain.com/auth/callback
    
  5. For preview deployments, add a wildcard pattern:
    https://*-your-project.vercel.app/auth/callback
    
The wildcard pattern (https://*-your-project.vercel.app/auth/callback) allows all Vercel preview URLs to work with authentication. This is optional but recommended for testing auth in preview deployments.
Supabase allows authentication callbacks from your Vercel domains.
4

Configure Stripe webhook (for payments)

Set up a production webhook endpoint in Stripe:
  1. Go to Stripe Dashboard
  2. Toggle to Live mode (top-right corner)
  3. Click Add endpoint
  4. Set Endpoint URL to:
    https://yourdomain.com/api/webhooks/stripe
    
    (Use your actual domain, not .vercel.app)
  5. Select Events to send:
    • customer.subscription.created
    • customer.subscription.updated
    • customer.subscription.deleted
    • invoice.payment_succeeded
    • invoice.payment_failed
  6. Click Add endpoint
  7. Copy the Signing secret (starts with whsec_...)
  8. Go back to Vercel Dashboard → Your Project → SettingsEnvironment Variables
  9. Update STRIPE_WEBHOOK_SECRET with the new signing secret
  10. Redeploy your project for the new secret to take effect
Critical: Use separate webhook endpoints and secrets for test mode (local development) and live mode (production). Never use the same webhook secret for both.
Preview deployments: If you want to test webhooks in preview deployments, create a separate webhook endpoint with test mode keys and a different signing secret.
Stripe webhook endpoint created, signing secret added to Vercel, and project redeployed.
5

Deploy to production

Trigger your first deployment:Option A: Deploy from Vercel Dashboard
  1. In the Vercel project configuration screen, click Deploy
  2. Vercel will build your project and deploy it
  3. Monitor the build logs for errors
Option B: Deploy via Git push
  1. Make a commit to your repository:
    git add .
    git commit -m "Deploy to production"
    git push origin main
    
  2. Vercel automatically deploys on every push to your main branch
Build succeeds and deployment completes. You’ll see “Ready” status with a URL.
Build time: ~2-4 minutes for a fresh Sabo deployment. Subsequent deploys are faster (~1-2 minutes) thanks to caching.
6

Verify deployment

Test that your deployed application works correctly:
  • Marketing Pages
  • Authentication
  • Dashboard
  • Payments (Stripe)
Test public pages (no auth required):
  • Homepage: https://yourdomain.com/
  • Pricing: https://yourdomain.com/pricing
  • Contact: https://yourdomain.com/contact
  • Blog: https://yourdomain.com/blog
  • Changelog: https://yourdomain.com/changelog
  • Legal pages: /privacy, /terms-of-service, /cookie-policy
All marketing pages load correctly with proper styling and navigation.
All core features verified and working in production.
7

Add custom domain (optional)

Connect a custom domain to your Vercel project:
  1. Go to Vercel Dashboard → Your Project → SettingsDomains
  2. Click Add and enter your domain (e.g., yourdomain.com)
  3. Follow DNS configuration instructions:
    • For root domain (yourdomain.com): Add A record pointing to Vercel’s IP
    • For subdomain (www.yourdomain.com): Add CNAME record pointing to cname.vercel-dns.com
  4. Wait for DNS propagation (usually 5-60 minutes)
  5. Vercel automatically issues SSL certificate via Let’s Encrypt
After domain is active:
  1. Update environment variable in Vercel:
    NEXT_PUBLIC_SITE_URL=https://yourdomain.com
    
  2. Update Supabase Auth URLs:
    • Site URL: https://yourdomain.com
    • Add redirect URL: https://yourdomain.com/auth/callback
  3. Update Stripe webhook endpoint URL:
    • Change endpoint URL to: https://yourdomain.com/api/webhooks/stripe
    • Copy new signing secret to Vercel env vars
  4. Redeploy your project for all changes to take effect
Custom domain is active with SSL, all URLs updated, and deployment successful.
8

Set up preview deployments

Vercel automatically creates preview deployments for every branch and pull request:
  • Preview URLs: https://your-project-git-branchname-yourteam.vercel.app
  • Pull request previews: Each PR gets a unique preview URL
  • Automatic deployment: Push to any branch triggers a preview build
Preview-specific environment variables:You can set different environment variables for Preview deployments (e.g., test Stripe keys, staging Supabase project):
  1. Go to Vercel Dashboard → Your Project → SettingsEnvironment Variables
  2. Add variables with Preview scope
  3. Previews will use these instead of Production values
Useful for:
  • Testing with Stripe test mode
  • Using a staging Supabase database
  • Sharing work-in-progress with your team
Add comments in pull requests to share preview URLs with team members for review.
Preview deployments working. Each branch push creates a new preview URL.

Production Optimization

Performance

Sabo is optimized for Vercel out of the box:
  • Automatic CDN caching for static assets
  • Edge runtime for fast middleware execution
  • Image optimization via Next.js Image component
  • Static generation for blog and changelog (built from MDX at deploy time—redeploy when content changes)
  • Server-side rendering (SSR) for dynamic pages
No additional configuration needed. Vercel handles all optimizations automatically.

Build Settings

Default build settings work for most cases:
Build Command: next build
Install Command: pnpm install
Output Directory: .next
Node Version: 20.x (auto-detected)
If deploying from a monorepo, set Root Directory to sabo (or your Sabo package path).

Environment Management

Organize environment variables by environment:
EnvironmentUse CaseExample Keys
ProductionLive site with real userssk_live_..., production Supabase
PreviewPR/branch testingsk_test_..., staging Supabase
DevelopmentLocal dev (.env.local)sk_test_..., local Supabase
Development environment variables are not synced to Vercel. Use .env.local for local development.

Troubleshooting

Symptoms:
  • Build logs show module import errors
  • TypeScript compilation fails
Solutions:
  1. Verify all dependencies are in package.json:
    pnpm install
    git add package.json pnpm-lock.yaml
    git commit -m "Update dependencies"
    git push
    
  2. Check for missing environment variables:
    • Build-time code referencing env vars will fail if vars are missing
    • Add missing vars in Vercel Dashboard
  3. Clear build cache:
    • Vercel Dashboard → Deployments → Latest build → menu → Redeploy
    • Check “Clear build cache and redeploy”
  4. Local build test:
    pnpm build
    
    If it fails locally, fix errors before deploying.
Symptoms:
  • process.env.VARIABLE_NAME is undefined
  • Features work locally but not in production
Solutions:
  1. Check variable naming:
    • Client-side variables must start with NEXT_PUBLIC_
    • Server-only variables should not have NEXT_PUBLIC_ prefix
  2. Verify variable scope:
    • Go to Vercel Dashboard → Settings → Environment Variables
    • Ensure variables have correct scope (Production/Preview/Development)
  3. Redeploy after adding variables:
    • Environment variables are only loaded at build time
    • After adding/changing vars, trigger a new deployment
  4. Check for typos:
    • Variable names are case-sensitive
    • SUPABASE_URLSUPABASE_url
Symptoms:
  • After signing in with OAuth, user sees error page
  • Email verification links redirect to error page
  • Console shows CORS or redirect errors
Solutions:
  1. Check Supabase Redirect URLs:
    • Go to Supabase Dashboard → Authentication → URL Configuration
    • Ensure your Vercel domain is in Redirect URLs list
    • Format: https://yourdomain.com/auth/callback
  2. Verify Site URL matches:
    • NEXT_PUBLIC_SITE_URL in Vercel must match Supabase Site URL
    • Include protocol (https://), no trailing slash
  3. Check for browser redirects:
    • Open browser DevTools → Network tab
    • Look for redirect chain
    • Verify final redirect goes to /auth/callback
  4. Test with different browsers/incognito:
    • Clear browser cache and cookies
    • Try in incognito/private window
    • Some browsers block third-party cookies
Symptoms:
  • Subscriptions don’t update in database
  • Payments succeed but user subscription status unchanged
  • Stripe Dashboard shows “Endpoint not responding”
Solutions:
  1. Verify endpoint URL is correct:
    • Stripe Dashboard → Webhooks → Your endpoint
    • URL should be: https://yourdomain.com/api/webhooks/stripe
    • Must use custom domain, not .vercel.app (for live mode)
  2. Check webhook signing secret:
    • Ensure STRIPE_WEBHOOK_SECRET in Vercel matches endpoint secret
    • Use live mode secret (whsec_...) for production
  3. Test webhook delivery:
    • Stripe Dashboard → Webhooks → Your endpoint
    • Click Send test webhook
    • Select event type (e.g., invoice.payment_succeeded)
    • Check Vercel logs for processing
  4. Review Vercel Function Logs:
    • Vercel Dashboard → Your Project → Logs
    • Filter by /api/webhooks/stripe
    • Look for errors or webhook signature verification failures
  5. Ensure events are selected:
    • Webhook endpoint must listen for:
      • customer.subscription.created
      • customer.subscription.updated
      • customer.subscription.deleted
      • invoice.payment_succeeded
      • invoice.payment_failed
Symptoms:
  • No events appear in PostHog dashboard
  • Console shows “PostHog is not initialized”
Solutions:
  1. Verify environment variables are set:
    NEXT_PUBLIC_POSTHOG_KEY=phc_...
    NEXT_PUBLIC_POSTHOG_HOST=https://app.posthog.com
    
  2. Redeploy after adding PostHog vars:
    • PostHog only initializes if env vars are present at build time
  3. Check browser console:
    • Open DevTools → Console
    • Look for PostHog initialization messages
    • Check Network tab for requests to app.posthog.com
  4. Verify PostHog project is active:
    • PostHog Dashboard → Project Settings
    • Ensure project is not paused or archived
Symptoms:
  • Vercel build exceeds time limit (10 minutes on free plan)
  • Build gets stuck on specific step
Solutions:
  1. Optimize dependencies:
    # Remove unused dependencies
    pnpm prune
    
    # Update outdated packages
    pnpm update
    
  2. Check for large files in repo:
    • Avoid committing node_modules/, .next/, or large assets
    • Use .gitignore to exclude build artifacts
  3. Upgrade Vercel plan:
    • Free tier: 10-minute build limit
    • Pro tier: 45-minute build limit
  4. Split large pages:
    • Use dynamic imports for heavy components
    • Implement code splitting for route segments
Symptoms:
  • Direct URL navigation works
  • Refreshing page shows 404
Solutions:
  1. This should not happen with Vercel + Next.js App Router.
    • Vercel automatically handles Next.js routing
  2. Check Vercel routing configuration:
    • Vercel Dashboard → Project Settings → General
    • Ensure “Framework Preset” is set to Next.js
  3. Verify build output:
    • Check Vercel build logs
    • Ensure .next directory contains expected routes
  4. Test with vercel dev:
    npm i -g vercel
    vercel dev
    
    Run locally with Vercel’s dev server to debug routing

Continuous Deployment

Vercel automatically deploys on every push to your Git repository:

Deployment Triggers

ActionResult
Push to main branchDeploys to Production
Push to any other branchCreates Preview deployment
Open pull requestCreates Preview with comment link
Merge PRDeploys to Production

Deployment Protection

Enable deployment protection for production:
  1. Vercel Dashboard → Project Settings → Git
  2. Enable Production Deployment Protection
  3. Only designated team members can approve production deploys
Set up Vercel GitHub integration to automatically comment on PRs with preview URLs.