Skip to main content

Vercel Deployment Guide

Deploy the Viben web platform (apps/web) to Vercel


Table of Contents

  1. Quick Start
  2. Prerequisites
  3. Project Configuration
  4. Environment Variables
  5. Deployment Steps
  6. Post-Deployment
  7. Troubleshooting
  8. CI/CD Integration

Quick Start

# 1. Install Vercel CLI (if not already installed)
npm i -g vercel

# 2. Login to Vercel
vercel login

# 3. Deploy from project root (monorepo)
vercel --cwd apps/web

# 4. Deploy to production
vercel --cwd apps/web --prod

Prerequisites

Required Accounts and Services

  1. Vercel Account

  2. Neon Database

    • PostgreSQL database instance
    • Get connection string from Neon dashboard
  3. GitHub OAuth App

    • Create at: GitHub Settings → Developer Settings → OAuth Apps
    • Set callback URL: https://your-domain.vercel.app/api/auth/github/callback
  4. HuggingFace Account (for package storage)

Local Requirements

  • Node.js 18+
  • pnpm (package manager)
  • Vercel CLI: npm i -g vercel

Project Configuration

Project Structure

viben/
├── apps/
│ └── web/ # Next.js app to deploy
│ ├── app/ # Next.js App Router
│ ├── components/ # React components
│ ├── lib/ # Utilities and configs
│ ├── next.config.ts
│ ├── vercel.json # Vercel configuration
│ └── package.json
├── packages/ # Shared packages (auto-bundled)
└── pnpm-workspace.yaml

Monorepo Detection

Vercel automatically detects:

  • Framework: Next.js (from next.config.ts)
  • Root Directory: apps/web (set in project settings)
  • Build Command: pnpm build (from vercel.json)
  • Install Command: pnpm install (from vercel.json)

vercel.json Configuration

Located at apps/web/vercel.json:

{
"framework": "nextjs",
"buildCommand": "pnpm build",
"installCommand": "pnpm install --prod=false",
"functions": {
"app/api/packages/upload/route.ts": {
"maxDuration": 300
},
"app/api/auth/github/callback/route.ts": {
"maxDuration": 30
}
},
"headers": [
{
"source": "/api/(.*)",
"headers": [
{
"key": "Access-Control-Allow-Origin",
"value": "*"
},
{
"key": "Access-Control-Allow-Methods",
"value": "GET, POST, PUT, DELETE, OPTIONS"
},
{
"key": "Access-Control-Allow-Headers",
"value": "Content-Type, Authorization"
}
]
}
]
}

Key Configurations:

  • Upload route: 5-minute timeout for large package uploads
  • Auth callback: 30-second timeout for OAuth flow
  • CORS: Enabled for all API routes

next.config.ts Configuration

{
turbopack: {
root: path.resolve(__dirname, '../..'),
},
outputFileTracingRoot: path.resolve(__dirname, '../..'),
images: {
remotePatterns: [
{ protocol: 'https', hostname: 'avatars.githubusercontent.com' },
{ protocol: 'https', hostname: 'github.com' },
{ protocol: 'https', hostname: 'huggingface.co' },
],
},
}

Important:

  • outputFileTracingRoot: Enables monorepo support (includes packages/)
  • images.remotePatterns: Whitelist for Next.js Image Optimization

Environment Variables

Required Environment Variables

Add these in Vercel Dashboard → Settings → Environment Variables:

VariableDescriptionExampleWhere to Get
POSTGRES_URLNeon PostgreSQL connection stringpostgresql://user:pass@host/db?sslmode=requireNeon Dashboard
JWE_SECRET32-byte secret for session encryptionGenerate with openssl rand -base64 32Generate locally
ENCRYPTION_KEY32-byte key for data encryptionGenerate with openssl rand -base64 32Generate locally
NEXT_PUBLIC_GITHUB_CLIENT_IDGitHub OAuth client IDIv1.abc123...GitHub OAuth App settings
GITHUB_CLIENT_SECRETGitHub OAuth client secretghp_abc123...GitHub OAuth App settings
HF_TOKENHuggingFace API tokenhf_abc123...HuggingFace → Settings → Tokens
HF_NAMESPACEHuggingFace username or orgyour-usernameYour HuggingFace profile
NEXT_PUBLIC_APP_URLProduction URLhttps://your-domain.vercel.appYour Vercel domain
NODE_ENVEnvironment modeproductionSet automatically by Vercel

Generate Secrets

# Generate JWE_SECRET (32 bytes)
openssl rand -base64 32

# Generate ENCRYPTION_KEY (32 bytes)
openssl rand -base64 32

GitHub OAuth Setup

  1. Go to: https://github.com/settings/developers
  2. Click "New OAuth App"
  3. Fill in:
    • Application name: Viben Platform
    • Homepage URL: https://your-domain.vercel.app
    • Authorization callback URL: https://your-domain.vercel.app/api/auth/github/callback
  4. Copy Client ID and Client secret

Environment Variable Scopes

Set for all environments (Production, Preview, Development):

  • ✅ All variables should be available in all environments
  • ⚠️ For Preview deployments, use a separate database (optional but recommended)

Deployment Steps

Step 1: First-Time Setup

  1. Import Project

  2. Configure Project

    • Root Directory: apps/web
    • Build Command: pnpm build (auto-detected from vercel.json)
    • Install Command: pnpm install
    • Output Directory: .next (auto-detected)
  3. Add Environment Variables

    • Click "Environment Variables"
    • Add all variables from the table above
    • Select scopes: Production, Preview, Development
  4. Deploy

    • Click "Deploy"
    • Wait for build to complete (~2-5 minutes)

Option B: Via CLI

# From project root
cd apps/web

# Link to Vercel project (first time only)
vercel link

# Set environment variables
vercel env add POSTGRES_URL production
vercel env add JWE_SECRET production
vercel env add ENCRYPTION_KEY production
# ... add all other variables

# Deploy to production
vercel --prod

Step 2: Database Migration

After first deployment, run database migrations:

# From apps/web directory
pnpm db:push

# Or generate and run migrations
pnpm db:generate
pnpm db:migrate

Note: For production, consider using Vercel's Postgres or running migrations via a deployment script.

Step 3: Verify Deployment

Check the following:

  • Homepage loads: https://your-domain.vercel.app
  • API health check: https://your-domain.vercel.app/api/health (if implemented)
  • GitHub OAuth login works
  • Database connection works (check admin panel)
  • Image optimization works (check avatar images)

Post-Deployment

Custom Domain Setup

  1. Add Domain

    • Vercel Dashboard → Settings → Domains
    • Add your custom domain (e.g., viben.com)
  2. Configure DNS

    • Add CNAME record: your-domain.comcname.vercel-dns.com
    • Or A record: 76.76.21.21
  3. Update Environment Variables

    # Update NEXT_PUBLIC_APP_URL
    vercel env add NEXT_PUBLIC_APP_URL production
    # Enter: https://your-custom-domain.com
  4. Update GitHub OAuth

    • Update callback URL in GitHub OAuth App settings
    • New URL: https://your-custom-domain.com/api/auth/github/callback

Performance Optimization

  1. Enable Edge Functions (Optional)

    • For API routes with global distribution
    • Add export const runtime = 'edge' to route files
  2. Configure Caching

    • Static assets: Auto-cached by Vercel CDN
    • API routes: Use Cache-Control headers
  3. Monitor Performance

    • Vercel Analytics: Dashboard → Analytics
    • Core Web Vitals tracking

Security Checklist

  • Environment variables are not committed to Git
  • Secrets are regenerated for production
  • GitHub OAuth app is configured with production URL
  • Database uses SSL connection (sslmode=require)
  • CORS is properly configured in vercel.json

Troubleshooting

Build Failures

Error: No database connection string was provided to neon()

Error Message:

Error: No database connection string was provided to `neon()`.
Perhaps an environment variable has not been set?

Cause: Next.js is trying to connect to the database during build time for static page generation, but POSTGRES_URL is not set in the build environment.

Fix 1: Add POSTGRES_URL to Vercel Environment Variables (Recommended)

Ensure POSTGRES_URL is added to all environments in Vercel:

  1. Go to Vercel Dashboard → Settings → Environment Variables
  2. Add POSTGRES_URL with your Neon connection string
  3. Important: Check Production, Preview, and Development
  4. Redeploy

Fix 2: Make database connection optional during build

If you don't need database access during build, make it optional:

// lib/db/index.ts
const connectionString = process.env.POSTGRES_URL || '';

// Only create db instance if connection string exists
export const db = connectionString
? drizzle(neon(connectionString), { schema })
: null;

Then check for db before using:

if (!db) {
return NextResponse.json({ error: 'Database not configured' }, { status: 500 });
}

Fix 3: Use dynamic imports for API routes

API routes that use the database should not be statically analyzed:

// In route files that use db
export const dynamic = 'force-dynamic';

Note: For production deployments, Fix 1 is recommended as it ensures all features work correctly.

Warning: Mismatching @next/swc version

Warning Message:

⚠ Mismatching @next/swc version, detected: 15.5.7 while Next.js is on 15.5.11

Cause: Next.js and @next/swc versions are out of sync. This happens when:

  • package.json uses ^15.1.0 (allows minor version updates)
  • Vercel installs the latest compatible version (e.g., 15.5.11)
  • But @next/swc binary hasn't been updated to match

Impact: Usually safe to ignore - this is just a warning, not an error. Build will complete successfully.

Fix (if you want to eliminate the warning):

  1. Update to specific version (recommended for production):

    # In apps/web directory
    pnpm add next@15.5.11
    pnpm install
    git commit -am "fix: lock Next.js to 15.5.11"
    git push
  2. Or clear Vercel cache and rebuild:

    • Vercel Dashboard → Settings → Build & Deploy
    • Under "Cache", click "Clear Cache"
    • Re-deploy
  3. Or add explicit @next/swc dependency (not recommended):

    pnpm add -D @next/swc-linux-x64-gnu@15.5.11

Best Practice: Lock to a specific Next.js version in production to ensure consistent builds:

{
"dependencies": {
"next": "15.5.11" // Remove ^ for production
}
}

Error: Module not found (monorepo packages)

Cause: Monorepo packages not included in build

Fix: Ensure outputFileTracingRoot is set in next.config.ts

outputFileTracingRoot: path.resolve(__dirname, '../..'),

Error: pnpm: command not found

Cause: Wrong package manager detected

Fix: Add to vercel.json:

{
"installCommand": "pnpm install"
}

Error: ERR_PNPM_INCLUDED_DEPS_CONFLICT / ESLint must be installed / Could not find declaration file for module 'bcrypt'

Error Messages:

ERR_PNPM_INCLUDED_DEPS_CONFLICT modules directory (at "/vercel/path0") was installed with optionalDependencies, dependencies. Current install wants optionalDependencies, dependencies, devDependencies.

ESLint must be installed in order to run during builds: pnpm install --save-dev eslint

Type error: Could not find a declaration file for module 'bcrypt'.

Cause: This is a known issue with pnpm monorepos on Vercel. By default, Vercel runs pnpm install in the root directory without installing devDependencies, but Next.js build requires typescript, eslint, @types/* and other devDependencies. When Next.js attempts to auto-install these dependencies, it conflicts with the existing node_modules structure.

Fix: Use --prod=false in vercel.json to force install devDependencies:

{
"installCommand": "pnpm install --prod=false"
}

Important Warning - Do Not Modify:

--prod=false is the correct solution. Do not move typescript, eslint, @types/bcrypt, etc. to dependencies for these reasons:

  1. Semantically incorrect - These are build-time tools, not runtime dependencies
  2. Increases production bundle size - Production servers don't need the TypeScript compiler
  3. Violates community conventions - All Next.js projects keep these in devDeps

Related commit: 792d6ee - fix(vercel): install devDependencies to fix build conflict

References:

Runtime Errors

Error: Database connection failed

Cause: Invalid POSTGRES_URL or database not accessible

Fix:

  1. Check environment variable in Vercel Dashboard
  2. Ensure Neon database allows connections from 0.0.0.0/0
  3. Verify ?sslmode=require is in connection string

Error: JWE decryption failed

Cause: JWE_SECRET or ENCRYPTION_KEY mismatch

Fix: Regenerate secrets and redeploy

Error: GitHub OAuth redirect URI mismatch

Cause: Callback URL doesn't match GitHub OAuth App settings

Fix: Update callback URL in GitHub OAuth App:

https://your-actual-domain.vercel.app/api/auth/github/callback

Function Timeouts

Error: Function Execution Timeout (10s)

Cause: Long-running API routes exceed default timeout

Fix: Increase timeout in vercel.json:

{
"functions": {
"app/api/your-route/route.ts": {
"maxDuration": 60
}
}
}

Limits:

  • Hobby plan: 10s
  • Pro plan: 60s
  • Enterprise plan: 900s

CI/CD Integration

Automatic Deployments

Vercel auto-deploys on:

  • Push to main: Production deployment
  • Pull requests: Preview deployment (unique URL)

Disable Auto-Deploy (Manual Control)

If you want manual control:

  1. Vercel Dashboard → Settings → Git
  2. Disable "Production Branch" auto-deploy
  3. Deploy manually: vercel --prod

GitHub Actions Integration

For custom build steps before deployment:

# .github/workflows/deploy.yml
name: Deploy to Vercel

on:
push:
branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 8

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18
cache: 'pnpm'

- name: Install dependencies
run: pnpm install

- name: Run tests
run: pnpm test --filter=@viben/web

- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
working-directory: apps/web

Required Secrets (GitHub repo settings):

  • VERCEL_TOKEN: Get from Vercel → Settings → Tokens
  • VERCEL_ORG_ID: Found in .vercel/project.json
  • VERCEL_PROJECT_ID: Found in .vercel/project.json

Monitoring and Maintenance

Health Checks

Create a health check endpoint:

// apps/web/app/api/health/route.ts
import { NextResponse } from 'next/server';
import { db } from '@/lib/db';

export async function GET() {
try {
// Check database connection
await db.execute('SELECT 1');

return NextResponse.json({
status: 'healthy',
timestamp: new Date().toISOString(),
});
} catch (error) {
return NextResponse.json(
{ status: 'unhealthy', error: String(error) },
{ status: 503 }
);
}
}

Log Monitoring

View logs:

  • Vercel Dashboard: Deployments → Logs
  • CLI: vercel logs your-project-url

Performance Monitoring

  • Vercel Analytics: Auto-enabled for all deployments
  • Vercel Speed Insights: Add @vercel/speed-insights package

Quick Reference

Common Commands

# Deploy to preview
vercel

# Deploy to production
vercel --prod

# Check deployment logs
vercel logs <deployment-url>

# List deployments
vercel ls

# Rollback to previous deployment
vercel rollback <deployment-url>

# Environment variables
vercel env ls
vercel env add <name> <environment>
vercel env rm <name> <environment>

Summary

Deployment Checklist:

  • Set up all environment variables
  • Configure GitHub OAuth callback URL
  • Set up Neon PostgreSQL database
  • Configure HuggingFace storage
  • Deploy to Vercel
  • Run database migrations
  • Verify all features work
  • Set up custom domain (optional)
  • Configure monitoring and alerts

Key Files:

  • apps/web/vercel.json - Vercel configuration
  • apps/web/next.config.ts - Next.js configuration
  • apps/web/.env.example - Environment variable template

Support:


Last Updated: 2026-02-05