Vercel Deployment Guide
Deploy the Viben web platform (
apps/web) to Vercel
Table of Contents
- Quick Start
- Prerequisites
- Project Configuration
- Environment Variables
- Deployment Steps
- Post-Deployment
- Troubleshooting
- 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
-
Vercel Account
- Sign up at https://vercel.com
- Connect your GitHub account (recommended)
-
Neon Database
- PostgreSQL database instance
- Get connection string from Neon dashboard
-
GitHub OAuth App
- Create at: GitHub Settings → Developer Settings → OAuth Apps
- Set callback URL:
https://your-domain.vercel.app/api/auth/github/callback
-
HuggingFace Account (for package storage)
- Create token at: https://huggingface.co/settings/tokens
- Need write access for uploading packages
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(fromvercel.json) - Install Command:
pnpm install(fromvercel.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 (includespackages/)images.remotePatterns: Whitelist for Next.js Image Optimization
Environment Variables
Required Environment Variables
Add these in Vercel Dashboard → Settings → Environment Variables:
| Variable | Description | Example | Where to Get |
|---|---|---|---|
POSTGRES_URL | Neon PostgreSQL connection string | postgresql://user:pass@host/db?sslmode=require | Neon Dashboard |
JWE_SECRET | 32-byte secret for session encryption | Generate with openssl rand -base64 32 | Generate locally |
ENCRYPTION_KEY | 32-byte key for data encryption | Generate with openssl rand -base64 32 | Generate locally |
NEXT_PUBLIC_GITHUB_CLIENT_ID | GitHub OAuth client ID | Iv1.abc123... | GitHub OAuth App settings |
GITHUB_CLIENT_SECRET | GitHub OAuth client secret | ghp_abc123... | GitHub OAuth App settings |
HF_TOKEN | HuggingFace API token | hf_abc123... | HuggingFace → Settings → Tokens |
HF_NAMESPACE | HuggingFace username or org | your-username | Your HuggingFace profile |
NEXT_PUBLIC_APP_URL | Production URL | https://your-domain.vercel.app | Your Vercel domain |
NODE_ENV | Environment mode | production | Set 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
- Go to: https://github.com/settings/developers
- Click "New OAuth App"
- 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
- 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
Option A: Via Vercel Dashboard (Recommended)
-
Import Project
- Go to: https://vercel.com/new
- Select your GitHub repository
- Framework Preset: Next.js (auto-detected)
-
Configure Project
- Root Directory:
apps/web - Build Command:
pnpm build(auto-detected fromvercel.json) - Install Command:
pnpm install - Output Directory:
.next(auto-detected)
- Root Directory:
-
Add Environment Variables
- Click "Environment Variables"
- Add all variables from the table above
- Select scopes: Production, Preview, Development
-
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
-
Add Domain
- Vercel Dashboard → Settings → Domains
- Add your custom domain (e.g.,
viben.com)
-
Configure DNS
- Add CNAME record:
your-domain.com→cname.vercel-dns.com - Or A record:
76.76.21.21
- Add CNAME record:
-
Update Environment Variables
# Update NEXT_PUBLIC_APP_URLvercel env add NEXT_PUBLIC_APP_URL production# Enter: https://your-custom-domain.com -
Update GitHub OAuth
- Update callback URL in GitHub OAuth App settings
- New URL:
https://your-custom-domain.com/api/auth/github/callback
Performance Optimization
-
Enable Edge Functions (Optional)
- For API routes with global distribution
- Add
export const runtime = 'edge'to route files
-
Configure Caching
- Static assets: Auto-cached by Vercel CDN
- API routes: Use
Cache-Controlheaders
-
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:
- Go to Vercel Dashboard → Settings → Environment Variables
- Add
POSTGRES_URLwith your Neon connection string - Important: Check Production, Preview, and Development
- 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.jsonuses^15.1.0(allows minor version updates)- Vercel installs the latest compatible version (e.g.,
15.5.11) - But
@next/swcbinary 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):
-
Update to specific version (recommended for production):
# In apps/web directorypnpm add next@15.5.11pnpm installgit commit -am "fix: lock Next.js to 15.5.11"git push -
Or clear Vercel cache and rebuild:
- Vercel Dashboard → Settings → Build & Deploy
- Under "Cache", click "Clear Cache"
- Re-deploy
-
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:
- Semantically incorrect - These are build-time tools, not runtime dependencies
- Increases production bundle size - Production servers don't need the TypeScript compiler
- 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:
- Check environment variable in Vercel Dashboard
- Ensure Neon database allows connections from
0.0.0.0/0 - Verify
?sslmode=requireis 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:
- Vercel Dashboard → Settings → Git
- Disable "Production Branch" auto-deploy
- 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 → TokensVERCEL_ORG_ID: Found in.vercel/project.jsonVERCEL_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-insightspackage
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>
Useful Links
- Vercel Dashboard: https://vercel.com/dashboard
- Vercel CLI Docs: https://vercel.com/docs/cli
- Next.js on Vercel: https://vercel.com/docs/frameworks/nextjs
- Monorepo Support: https://vercel.com/docs/monorepos
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 configurationapps/web/next.config.ts- Next.js configurationapps/web/.env.example- Environment variable template
Support:
- Vercel Support: https://vercel.com/support
- Viben Issues: GitHub Issues
Last Updated: 2026-02-05