Vercel Deployment Cheat Sheet
Deploy and manage frontend apps on Vercel using the CLI, project configuration, environment variables, and serverless functions.
Vercel CLI Basics
Install and use the Vercel CLI to deploy projects.
npm i -g vercel # Install CLIvercel login # Authenticatevercel # Deploy current dir (preview)vercel --prod # Deploy to productionvercel dev # Run local dev server matching prodvercel ls # List deploymentsvercel rm <deployment-url> # Remove a deploymentvercel logs <deployment-url> # Tail deployment logsvercel env pull .env.local # Pull env vars locally
vercel.json Config
Customize builds, routes, and headers.
{ "buildCommand": "npm run build", "outputDirectory": "dist", "framework": "nextjs", "rewrites": [ { "source": "/api/(.*)", "destination": "/api/$1" } ], "headers": [ { "source": "/(.*)", "headers": [ { "key": "X-Frame-Options", "value": "DENY" } ] } ]}
Serverless Function
Add an API route deployed as a Vercel serverless function.
// api/hello.jsexport default function handler(req, res) { const { name = 'world' } = req.query; res.status(200).json({ message: `Hello, ${name}!` });}// Edge function variant:export const config = { runtime: 'edge' };export default function handler(req) { return new Response('Hello from the edge');}
Environment Variables & Domains
Manage secrets and custom domains per environment.
- Production/Preview/Development- three scopes for env vars, set independently in Project Settings or via `vercel env add`
- vercel env add <NAME>- adds an environment variable and prompts for target environments
- NEXT_PUBLIC_*- prefix required for Next.js env vars exposed to the browser
- vercel domains add- attaches a custom domain to a project
- vercel alias- points a stable URL/domain at a specific deployment
- Git integration- pushing to a connected GitHub/GitLab repo triggers automatic preview deployments per branch/PR
- vercel.json redirects- define permanent or temporary redirects declaratively
Edge Middleware
Run logic before a request completes for auth gating, A/B tests, or geo-based rewrites.
// middleware.js (runs at the Edge, before routing)import { NextResponse } from 'next/server';export function middleware(request) { const country = request.geo?.country ?? 'US'; const token = request.cookies.get('session')?.value; if (!token && request.nextUrl.pathname.startsWith('/dashboard')) { return NextResponse.redirect(new URL('/login', request.url)); } const response = NextResponse.next(); response.headers.set('x-country', country); return response;}export const config = { matcher: ['/dashboard/:path*', '/api/:path*'] };
Incremental Static Regeneration & On-Demand Revalidation
Serve static pages that refresh on a timer or instantly via a webhook-triggered API route.
// app/blog/[slug]/page.jsexport const revalidate = 3600; // ISR: regenerate at most hourly// app/api/revalidate/route.js — call from a CMS webhook on publishimport { revalidatePath, revalidateTag } from 'next/cache';export async function POST(request) { const { path, secret } = await request.json(); if (secret !== process.env.REVALIDATE_SECRET) { return new Response('Invalid token', { status: 401 }); } revalidatePath(path); revalidateTag('posts'); return Response.json({ revalidated: true, now: Date.now() });}
Vercel Cron Jobs
Schedule recurring invocations of a serverless function without an external scheduler.
// vercel.json{ "crons": [ { "path": "/api/cron/cleanup", "schedule": "0 3 * * *" }, { "path": "/api/cron/digest", "schedule": "*/15 * * * *" } ]}// api/cron/cleanup.js — Vercel adds an Authorization header for cron invocationsexport default function handler(req, res) { if (req.headers.authorization !== `Bearer ${process.env.CRON_SECRET}`) { return res.status(401).end(); } // ...perform cleanup... res.status(200).json({ ok: true });}
Monorepo Root Directory & Project Linking
Deploy one app out of a monorepo and manage multiple linked Vercel projects from one repo.
vercel link # interactively link cwd to a Vercel projectvercel link --project my-web-app # link non-interactively# .vercel/project.json is created per linked directory — commit it to .gitignore# In Project Settings > Root Directory, set e.g. "apps/web" so Vercel# only rebuilds when files under that path change (Ignored Build Step):git diff HEAD^ HEAD --quiet ./apps/web || exit 1
Platform Internals & Limits
Behavior and constraints that only surface once you push past a hello-world deploy.
- Function duration limits- 10s (Hobby), 60s (Pro), 900s (Enterprise) for serverless functions; Edge functions cap at ~30s CPU time
- Immutable deployments- every deployment gets a unique URL and is never overwritten; `vercel alias` just repoints a domain
- Skew protection- keeps in-flight clients pinned to the deployment version their JS bundle was built against during a rollout
- Instant Rollback- `vercel rollback <deployment-url>` repoints production traffic immediately without a rebuild
- Build cache- `node_modules`/`.next/cache` persist between builds automatically; `vercel --force` bypasses it
- Speed Insights / Web Analytics- opt-in packages that report real-user Core Web Vitals per deployment
- Regional Edge Config- a low-latency key-value store readable from Middleware without a database round trip
Use Vercel's Preview Deployments (one per pull request) to share working URLs with reviewers before merging — combine with branch-specific env vars to test against staging APIs safely.