Complete Vercel integration skill pack with 30 skills covering deployments, edge functions, preview environments, performance optimization, and production operations. Flagship+ tier vendor pack.
Installation
Open Claude Code and run this command:
/plugin install vercel-pack@claude-code-plugins-plus
Use --global to install for all projects, or --project for current project only.
Skills (30)
Advanced debugging for hard-to-diagnose Vercel issues including cold starts, edge errors, and function tracing.
Vercel Advanced Troubleshooting
Overview
Diagnose hard-to-find Vercel issues: intermittent cold start failures, edge function crashes, region-specific behavior, function bundling problems, and serverless concurrency issues. Uses systematic isolation, request tracing, and Vercel-specific debugging techniques.
Prerequisites
- Vercel CLI with access to production logs
- Familiarity with
vercel-common-errors(standard debugging) curlandjqfor API inspection- Access to deployment inspection tools
Instructions
Step 1: Request-Level Tracing
# Trace a single request through Vercel's edge network
curl -v https://yourdomain.com/api/endpoint 2>&1 | grep -E "x-vercel|cf-ray|age|cache"
# Key headers to check:
# x-vercel-id: <region>::<function-id> — which region served the request
# x-vercel-cache: HIT/MISS/STALE — edge cache status
# x-vercel-execution-region: iad1 — function execution region
# age: 45 — seconds since edge cached the response
# x-matched-path: /api/endpoint — routing match result
Step 2: Cold Start Investigation
// Instrument cold start timing in your function
let coldStart = true;
const initTime = Date.now();
export default function handler(req, res) {
const isCold = coldStart;
coldStart = false;
const handlerStart = Date.now();
// ... your logic ...
res.setHeader('x-cold-start', String(isCold));
res.setHeader('x-init-duration', String(handlerStart - initTime));
res.json({
coldStart: isCold,
initDuration: isCold ? handlerStart - initTime : 0,
handlerDuration: Date.now() - handlerStart,
region: process.env.VERCEL_REGION,
});
}
# Measure cold start frequency over N requests
for i in $(seq 1 20); do
curl -s https://yourdomain.com/api/endpoint \
| jq '{coldStart, initDuration, region}'
sleep 2 # Wait between requests to allow isolate recycling
done
Step 3: Function Bundle Analysis
# Check what's being bundled into your function
vercel inspect https://my-app-xxx.vercel.app
# Check function sizes in the deployment
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
"https://api.vercel.com/v13/deployments/dpl_xxx" \
| jq '.functions | to_entries[] | {path: .key, size: .value.size, regions: .value.regions}'
# Locally — check what @vercel/nft traces for a function
npx @vercel/nft print api/heavy-endpoint.ts 2>/dev/null | head -50
# Shows all files that will be bundled
# Find unexpectedly large dependencies
npx @vercel/nft print api/heavy-endpoint.ts 2>/dev/null \
| xargs -I {} du -sh {} 2>/dev/null | sort -rh | head -20
Step 4: Region-Specific Debugging
Choose and implement Vercel architecture blueprints for different scales and use cases.
Vercel Architecture Variants
Overview
Choose the right Vercel architecture based on team size, traffic patterns, and technical requirements. Covers five validated blueprints from static site to multi-project enterprise deployment, with migration paths between them.
Prerequisites
- Understanding of team size and traffic requirements
- Knowledge of Vercel deployment model (edge, serverless, static)
- Clear SLA requirements
Instructions
Variant 1: Static Site (JAMstack)
Best for: Marketing sites, docs, blogs, landing pages
Team size: 1-3 developers
Traffic: Any (fully CDN-served)
project/
├── public/ # Static assets
├── src/
│ ├── pages/ # Static pages (SSG)
│ └── components/ # React components
├── vercel.json # Headers, redirects
└── package.json
// vercel.json
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Cache-Control", "value": "public, max-age=3600, stale-while-revalidate=86400" }
]
}
]
}
Key decisions:
- No serverless functions needed
- All pages pre-rendered at build time
- ISR for pages that update periodically
- Cost: minimal (mostly bandwidth)
Variant 2: Full-Stack Next.js (Most Common)
Best for: SaaS applications, dashboards, e-commerce
Team size: 2-10 developers
Traffic: Low to high
project/
├── src/
│ ├── app/
│ │ ├── api/ # Serverless API routes
│ │ ├── (marketing)/ # Static public pages
│ │ └── dashboard/ # Dynamic authenticated pages
│ ├── lib/ # Shared utilities
│ ├── components/ # UI components
│ └── middleware.ts # Edge auth + routing
├── prisma/ # Database schema
├── vercel.json
└── package.json
// vercel.json
{
"regions": ["iad1"],
"functions": {
"src/app/api/**/*.ts": {
"maxDuration": 30,
"memory": 1024
}
}
}
Key decisions:
- Mixed rendering: SSG for marketing, SSR for dashboard
- API routes in
app/api/for backend logic - Edge Middleware for auth (runs before every request)
- Database in same region as functions
Variant 3: API-Only Backend
Best for: Mobile app backends, microservices, webhook processors
Team size: 1-5 developers
Traffic: API-driven
project/
├── api/ # Serverless functions (one perConfigure Vercel CI/CD with GitHub Actions, preview deployments, and automated testing.
Vercel CI Integration
Overview
Set up automated Vercel deployments in GitHub Actions with preview deployments on PRs, production deploys on merge to main, and optional test gating. Covers both Vercel's built-in Git integration and custom CI pipelines using the Vercel CLI.
Prerequisites
- GitHub repository with Actions enabled
- Vercel project linked to the repo
VERCEL_TOKENstored as GitHub SecretVERCELORGIDandVERCELPROJECTIDfrom.vercel/project.json
Instructions
Step 1: Store CI Secrets in GitHub
# Get project and org IDs
cat .vercel/project.json
# {"orgId":"team_xxx","projectId":"prj_xxx"}
# Add secrets to GitHub repo
gh secret set VERCEL_TOKEN --body "your-vercel-token"
gh secret set VERCEL_ORG_ID --body "team_xxx"
gh secret set VERCEL_PROJECT_ID --body "prj_xxx"
Step 2: GitHub Actions — Preview on PR
# .github/workflows/vercel-preview.yml
name: Vercel Preview Deployment
on:
pull_request:
branches: [main]
jobs:
deploy-preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Vercel CLI
run: npm install -g vercel@latest
- name: Pull Vercel Environment
run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
- name: Build Project
run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
- name: Deploy Preview
id: deploy
run: |
url=$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }})
echo "preview_url=$url" >> $GITHUB_OUTPUT
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
- name: Comment PR with Preview URL
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `Preview deployed: ${{ steps.deploy.outputs.preview_url }}`
})
Step 3: GitHub Actions — Production on Merge
# .github/workflows/vercel-production.yml
name: Vercel Production Deployment
on:
push:
branches: [main]
jobs:
deploy-production:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Vercel CLI
run: npm install -g verceDiagnose and fix common Vercel deployment and function errors.
Vercel Common Errors
Overview
Diagnose and resolve the most common Vercel errors across three layers: build pipeline, serverless function runtime, and edge network. Each error includes the error code, root cause, and step-by-step fix.
Prerequisites
- Vercel CLI installed
- Access to deployment logs (
vercel logs) - Access to Vercel dashboard for build logs
Instructions
Step 1: Identify the Error Layer
# Check deployment status and error details
vercel inspect <deployment-url>
# View function runtime logs
vercel logs <deployment-url> --follow
# View build logs via API
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
"https://api.vercel.com/v13/deployments/dpl_xxx" | jq '.state, .errorMessage'
Three error layers:
- Build errors — appear during
vercel deploy, exit codes in build log - Runtime errors — appear when functions are invoked, visible in function logs
- Edge/routing errors — HTTP errors from Vercel's edge network
Step 2: Build Errors
BUILD_FAILED — Build command exited with non-zero code
Error: Command "npm run build" exited with 1
- Check:
vercel.json→buildCommandmatches your build script - Check: all dependencies listed in
package.json(not just devDependencies for runtime deps) - Fix: run
npm run buildlocally to reproduce
MISSINGBUILDSCRIPT — No build command found
Error: Missing Build Command
- Fix: add
"build"topackage.jsonscripts or setbuildCommandin vercel.json - For static sites: set
buildCommandto empty string or"true"
FUNCTIONPAYLOADTOO_LARGE — Serverless function bundle > 250 MB
Error: The Serverless Function "api/heavy" is 267 MB which exceeds the maximum size of 250 MB
- Fix: add unused packages to
.vercelignore, use dynamic imports, split into smaller functions - Check:
@vercel/nfttrace output to see what is being bundled
Step 3: Runtime Errors
FUNCTIONINVOCATIONFAILED — Unhandled exception in function
# View the actual error
vercel logs <deployment-url> --output=short
- Common causes: undefined env var, missing database connection, unhandled promise rejection
- Fix: wrap handler in try/catch, verify all env vars are set for the target enviro
Optimize Vercel costs through plan selection, function efficiency, and usage monitoring.
Vercel Cost Tuning
Overview
Optimize Vercel costs by understanding the Fluid Compute pricing model, reducing function execution time, leveraging edge caching to avoid function invocations, and configuring spend management. Covers plan comparison, cost drivers, and monitoring.
Prerequisites
- Access to Vercel billing dashboard
- Understanding of current deployment architecture
- Access to Vercel Analytics for usage patterns
Instructions
Step 1: Understand the Pricing Model
Vercel uses Fluid Compute pricing (for new projects):
| Resource | Hobby (Free) | Pro ($20/member/mo) | Enterprise |
|---|---|---|---|
| Bandwidth | 100 GB | 1 TB included | Custom |
| Serverless Execution | 100 GB-hrs | 1000 GB-hrs included | Custom |
| Edge Function invocations | 500K | 1M included | Custom |
| Edge Middleware invocations | 1M | 1M included | Custom |
| Image Optimizations | 1000 | 5000 included | Custom |
| Builds per day | 6000 | 6000 | Custom |
| Concurrent builds | 1 | 1 (more available) | Custom |
Fluid Compute billing breakdown:
- Active CPU time: charged per ms of actual CPU usage
- Provisioned memory: charged per GB-second of allocated memory
- Benefit: you pay for actual work, not idle waiting (e.g., waiting for a database response)
Step 2: Identify Cost Drivers
# Check usage via API
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
"https://api.vercel.com/v2/usage" | jq .
# Top cost drivers on Vercel:
# 1. Serverless function execution time (CPU + memory)
# 2. Bandwidth (large responses, unoptimized images)
# 3. Edge Middleware invocations (runs on EVERY request)
# 4. Image optimizations (each unique transform costs)
# 5. Build minutes (frequent deploys or slow builds)
Step 3: Reduce Function Execution Costs
// 1. Right-size function memory — don't over-allocate
// vercel.json
{
"functions": {
"api/lightweight.ts": { "memory": 128 }, // Simple JSON responses
"api/standard.ts": { "memory": 512 }, // Database queries
"api/heavy.ts": { "memory": 1024 } // Image processing
}
}
// 2. Move read-only endpoints to Edge Functions (cheaper, no cold starts)
// api/config.ts
export const config = { runtime: 'edge' };
export default function handler() {
return Response.json({ features: ['a', 'b'] });
Implement data handling, PII protection, and GDPR/CCPA compliance for Vercel deployments.
Vercel Data Handling
Overview
Handle sensitive data correctly on Vercel: PII redaction in logs, GDPR-compliant data processing in serverless functions, secure cookie management, and data residency configuration. Covers both what Vercel stores and what your application should protect.
Prerequisites
- Understanding of GDPR/CCPA requirements
- Vercel Pro or Enterprise (for data residency options)
- Logging infrastructure with PII awareness
Instructions
Step 1: Understand What Vercel Stores
| Data Type | Where | Retention | Control |
|---|---|---|---|
| Runtime logs | Vercel servers | 1hr (free), 30d (Plus) | Log drains |
| Build logs | Vercel servers | 30 days | Automatic |
| Analytics data | Vercel | Aggregated, no PII | Disable in dashboard |
| Deployment source | Vercel | Until deleted | Manual deletion |
| Environment variables | Vercel (encrypted) | Until deleted | Scoped access |
Step 2: PII Redaction in Logs
// lib/redact.ts — redact PII before logging
const PII_PATTERNS: [RegExp, string][] = [
[/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g, '[EMAIL]'],
[/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g, '[PHONE]'],
[/\b\d{3}-\d{2}-\d{4}\b/g, '[SSN]'],
[/\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g, '[CARD]'],
[/\b(?:Bearer|token|key|secret|password)\s*[:=]\s*\S+/gi, '[CREDENTIAL]'],
];
export function redact(text: string): string {
let result = text;
for (const [pattern, replacement] of PII_PATTERNS) {
result = result.replace(pattern, replacement);
}
return result;
}
// Usage — always redact before console.log
import { redact } from '@/lib/redact';
export async function POST(request: Request) {
const body = await request.json();
console.log('Request received:', redact(JSON.stringify(body)));
// Process safely...
}
Step 3: GDPR-Compliant API Routes
// api/users/[id]/route.ts — data subject request handlers
import { NextRequest, NextResponse } from 'next/server';
import { db } from '@/lib/db';
// Right to Access (GDPR Art. 15)
export async function GET(
request: NextRequest,
{ params }: { params: { id: string } }
) {
const user = await db.user.findUnique({
where: { id: params.id },
include: { posts: true, preferences: true },
});
if (!user) return NextResponse.json({ error: 'Not found' }, { status: 404 });
return NextResponse.json({
personalData: {
name: user.name,
email: user.email,
createdAt: user.createdAt,
posts: user.posts,
preferences: user.preferences,
Collect Vercel debug evidence for support tickets and troubleshooting.
Vercel Debug Bundle
Overview
Collect a comprehensive debug bundle containing deployment state, function logs, environment configuration, and build output for Vercel support escalation or team troubleshooting.
Current State
!vercel --version 2>/dev/null || echo 'Vercel CLI not installed'
!node --version 2>/dev/null || echo 'Node.js N/A'
Prerequisites
- Vercel CLI installed and authenticated
- Access to the affected deployment
jqfor JSON processing (recommended)
Instructions
Step 1: Collect Deployment Information
#!/usr/bin/env bash
set -euo pipefail
DEPLOY_URL="${1:-$(vercel ls --json 2>/dev/null | jq -r '.[0].url')}"
BUNDLE_DIR="vercel-debug-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$BUNDLE_DIR"
echo "=== Collecting debug bundle for: $DEPLOY_URL ==="
# Deployment inspection
vercel inspect "$DEPLOY_URL" > "$BUNDLE_DIR/inspect.txt" 2>&1 || true
# Deployment details via API
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
"https://api.vercel.com/v13/deployments/$DEPLOY_URL" \
| jq '{uid, name, state, target, readyState, errorMessage, meta, regions}' \
> "$BUNDLE_DIR/deployment.json" 2>/dev/null || true
Step 2: Collect Function Logs
# Recent function logs (last 100 entries)
vercel logs "$DEPLOY_URL" --output=short --limit=100 \
> "$BUNDLE_DIR/function-logs.txt" 2>&1 || true
# Function logs via API with filtering
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
"https://api.vercel.com/v2/deployments/$DEPLOY_URL/events?limit=100&direction=backward" \
| jq '.[] | {timestamp: .created, type, text}' \
> "$BUNDLE_DIR/events.json" 2>/dev/null || true
Step 3: Collect Build Output
# Build logs
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
"https://api.vercel.com/v13/deployments/$DEPLOY_URL" \
| jq '.build' > "$BUNDLE_DIR/build-info.json" 2>/dev/null || true
# List all functions in the deployment
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
"https://api.vercel.com/v13/deployments/$DEPLOY_URL" \
| jq '.routes, .functions' > "$BUNDLE_DIR/routes-functions.json" 2>/dev/null || true
Step 4: Collect Environment State (Redacted)
# Environment variable names only (no values)
vercel env ls > "$BUNDLE_DIR/env-vars-list.txt" 2>&1 || true
# Project configuration (redacted)
if [ -f "vercel.json" ]; then
cp vercel.json "$BUNDLE_DIR/vercel.json"
fi
# Package versions
if [ -f "pacDeploy and manage Vercel production deployments with promotion, rollback, and multi-region strategies.
Vercel Deploy Integration
Overview
Deploy Vercel applications to production using CLI, API, and Git-triggered workflows. Covers deployment promotion, instant rollback, rolling releases, multi-region function configuration, and deploy hooks for headless CMS integration.
Prerequisites
- Vercel project linked and configured
- Production environment variables set
- Custom domain configured (optional)
VERCEL_TOKENfor API-based deployments
Instructions
Step 1: Production Deploy Methods
# Method 1: CLI direct production deploy
vercel --prod
# Method 2: Promote a preview deployment to production
vercel promote https://my-app-preview-xxx.vercel.app
# Method 3: API-based deployment
curl -X POST "https://api.vercel.com/v13/deployments" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-app",
"target": "production",
"gitSource": {
"type": "github",
"repoId": "123456789",
"ref": "main",
"sha": "'$(git rev-parse HEAD)'"
}
}'
# Method 4: Deploy Hook (for CMS-triggered rebuilds)
curl -X POST "https://api.vercel.com/v1/integrations/deploy/prj_xxx/hook_xxx"
Step 2: Instant Rollback
# Roll back to the previous production deployment (no rebuild)
vercel rollback
# Roll back to a specific deployment
vercel rollback dpl_xxxxxxxxxxxx
# Verify the rollback
vercel ls --prod
curl -s https://yourdomain.com/api/health | jq .
# Via API — promote a known-good deployment
curl -X POST "https://api.vercel.com/v9/projects/my-app/promote" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{"deploymentId": "dpl_known_good_id"}'
Key points:
- Instant rollback swaps production traffic without rebuilding
- The rolled-back deployment retains its original environment variables
- All production domains immediately point to the rolled-back deployment
Step 3: Rolling Releases (Gradual Rollout)
Configure rolling releases in the dashboard under Settings > Rolling Releases:
// vercel.json — rolling release config
{
"rollingRelease": {
"enabled": true,
"stages": [
{ "targetPercentage": 10, "duration": 300 },
{ "targetPercentage": 50, "duration": 600 },
{ "targetPercentage": 100 }
]
}
}
This routes 10% of traffic to the new deployment for 5 minutes, then 50% for 10 minutes, then 100%. If
Create and manage Vercel preview deployments for branches and pull requests.
Vercel Deploy Preview
Overview
Deploy preview environments for branches and pull requests. Every git push to a non-production branch generates a unique preview URL. Covers CLI-based previews, API-based previews, deployment protection, and comment integration.
Prerequisites
- Completed
vercel-install-authsetup - Project linked via
vercel link - Git repository connected in Vercel dashboard
Instructions
Step 1: Deploy Preview via CLI
# Deploy current directory to a preview URL (default — not --prod)
vercel
# Output:
# 🔗 Linked to your-team/my-app
# 🔍 Inspect: https://vercel.com/your-team/my-app/AbCdEfG
# ✅ Preview: https://my-app-git-feature-branch-your-team.vercel.app
# Deploy a specific directory
vercel ./dist
# Deploy and wait for build to complete (useful in CI)
vercel --no-wait # returns immediately with deployment URL
Step 2: Deploy Preview via REST API
# Create a deployment via API — useful for custom CI pipelines
curl -X POST "https://api.vercel.com/v13/deployments" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-app",
"target": "preview",
"gitSource": {
"type": "github",
"repoId": "123456789",
"ref": "feature/new-feature",
"sha": "abc123def456"
}
}'
Step 3: Check Deployment Status
# Poll deployment status until READY
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
"https://api.vercel.com/v13/deployments/dpl_xxxxxxxxxxxx" \
| jq '{state: .state, url: .url, readyState: .readyState}'
# States: QUEUED → BUILDING → READY (or ERROR/CANCELED)
// Programmatic polling
async function waitForDeployment(client: VercelClient, deploymentId: string) {
while (true) {
const d = await client.getDeployment(deploymentId);
if (d.state === 'READY') return d;
if (d.state === 'ERROR' || d.state === 'CANCELED') {
throw new Error(`Deployment ${d.state}: ${deploymentId}`);
}
await new Promise(r => setTimeout(r, 5000)); // poll every 5s
}
}
Step 4: Configure Preview Environment Variables
# Add env vars scoped to preview only
vercel env add DATABASE_URL preview
# Enter value when prompted
# Or via API — scope to preview environment
curl -X POST "https://api.vercel.com/v9/projects/my-app/env" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"key": "DATABASE_URBuild and deploy Vercel Edge Functions for ultra-low latency at the edge.
Vercel Edge Functions
Overview
Edge Functions run on Vercel's Edge Network (V8 isolates) close to the user with no cold starts. They use Web Standard APIs (Request, Response, fetch) instead of Node.js APIs. Ideal for authentication, A/B testing, geolocation routing, and low-latency API responses.
Prerequisites
- Completed
vercel-install-authsetup - Familiarity with Web APIs (Request/Response)
- Node.js 18+ for local development
Instructions
Step 1: Create an Edge Function
// api/edge-hello.ts
// Export `runtime = 'edge'` to run on the Edge Runtime
export const config = { runtime: 'edge' };
export default function handler(request: Request): Response {
return new Response(
JSON.stringify({
message: 'Hello from the Edge!',
region: request.headers.get('x-vercel-ip-city') ?? 'unknown',
timestamp: Date.now(),
}),
{
status: 200,
headers: { 'Content-Type': 'application/json' },
}
);
}
Step 2: Edge Function with Geolocation
Vercel injects geolocation headers into every edge request:
// api/geo.ts
export const config = { runtime: 'edge' };
export default function handler(request: Request): Response {
const city = request.headers.get('x-vercel-ip-city') ?? 'unknown';
const country = request.headers.get('x-vercel-ip-country') ?? 'unknown';
const region = request.headers.get('x-vercel-ip-country-region') ?? 'unknown';
const latitude = request.headers.get('x-vercel-ip-latitude');
const longitude = request.headers.get('x-vercel-ip-longitude');
return Response.json({
city: decodeURIComponent(city),
country,
region,
coordinates: latitude && longitude ? { lat: latitude, lng: longitude } : null,
});
}
Step 3: Edge Middleware (middleware.ts)
Middleware runs before every request and can rewrite, redirect, or add headers:
// middleware.ts (must be at project root or src/)
import { NextRequest, NextResponse } from 'next/server';
export function middleware(request: NextRequest) {
// Example 1: Redirect based on country
const country = request.geo?.country ?? 'US';
if (country === 'DE') {
return NextResponse.redirect(new URL('/de', request.url));
}
// Example 2: A/B testing with cookies
const bucket = request.cookies.get('ab-bucket')?.value;
if (!bucket) {
const response = NextResponse.next();
response.cookies.set('ab-bucket', Math.random() > 0.5 ? 'a' : 'b');
return response;
}
// Example 3: Add security headers
const response = NextResponse.next();
response.headers.set('X-Frame-Options&Configure Vercel enterprise RBAC, access groups, SSO integration, and audit logging.
Vercel Enterprise RBAC
Overview
Configure Vercel's role-based access control (RBAC) with team roles, project-level access groups, SSO/SAML integration, and audit logging. Covers the two access control planes: team-level (who can deploy) and application-level (who can access deployed content).
Prerequisites
- Vercel Pro or Enterprise plan
- Identity Provider (IdP) with SAML 2.0 support (for SSO)
- Understanding of your organization's access requirements
Instructions
Step 1: Understand Vercel's Role Model
Team-Level Roles:
| Role | Deploy Prod | Manage Projects | Manage Billing | Manage Members |
|---|---|---|---|---|
| Owner | Yes | Yes | Yes | Yes |
| Member | Yes | Yes | No | No |
| Developer | Preview only | Limited | No | No |
| Viewer | No | Read-only | No | No |
| Security (Enterprise) | No | Security settings | No | No |
Extended Permissions (Enterprise):
Layer on top of base roles for granular control:
- Deploy to production
- Manage environment variables
- Manage domains
- Access runtime logs
- Manage integrations
Step 2: Configure Team Members via API
# Invite a team member
curl -X POST "https://api.vercel.com/v1/teams/team_xxx/members" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email": "developer@company.com",
"role": "DEVELOPER"
}'
# List team members
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
"https://api.vercel.com/v2/teams/team_xxx/members" \
| jq '.members[] | {name: .name, email: .email, role: .role}'
# Update a member's role
curl -X PATCH "https://api.vercel.com/v1/teams/team_xxx/members/user_xxx" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{"role": "MEMBER"}'
# Remove a team member
curl -X DELETE "https://api.vercel.com/v1/teams/team_xxx/members/user_xxx" \
-H "Authorization: Bearer $VERCEL_TOKEN"
Step 3: Access Groups (Project-Level Permissions)
Access Groups assign teams of people to specific projects with specific roles:
- Go to Team Settings > Access Groups
- Create a group (e.g., "Frontend Team", "Backend Team")
- Add members to the group
- Assign the group to specific projects with a role
Example Access Group SetupCreate a minimal working Vercel deployment with a serverless API route.
Vercel Hello World
Overview
Deploy a minimal project to Vercel with a static page and a serverless API route. Confirms your CLI auth, project structure, and deployment pipeline work end to end.
Prerequisites
- Completed
vercel-install-authsetup - Vercel CLI installed and authenticated
- Node.js 18+
Instructions
Step 1: Create Project Structure
mkdir my-vercel-app && cd my-vercel-app
npm init -y
Create the static landing page:
<!-- public/index.html -->
<!DOCTYPE html>
<html>
<head><title>Hello Vercel</title></head>
<body>
<h1>Hello from Vercel</h1>
<p id="result">Loading...</p>
<script>
fetch('/api/hello')
.then(r => r.json())
.then(d => document.getElementById('result').textContent = d.message);
</script>
</body>
</html>
Step 2: Create Serverless API Route
// api/hello.ts
import type { VercelRequest, VercelResponse } from '@vercel/node';
export default function handler(req: VercelRequest, res: VercelResponse) {
res.status(200).json({
message: 'Hello from Vercel Serverless Function!',
timestamp: new Date().toISOString(),
region: process.env.VERCEL_REGION || 'local',
});
}
Install the types:
npm install --save-dev @vercel/node typescript
Step 3: Add vercel.json Configuration
{
"rewrites": [
{ "source": "/api/(.*)", "destination": "/api/$1" }
],
"headers": [
{
"source": "/api/(.*)",
"headers": [
{ "key": "Cache-Control", "value": "s-maxage=0, stale-while-revalidate" }
]
}
]
}
Step 4: Deploy Preview
# Deploy to a preview URL (not production)
vercel
# Output:
# Vercel CLI 39.x.x
# 🔗 Linked to your-team/my-vercel-app
# 🔍 Inspect: https://vercel.com/your-team/my-vercel-app/xxx
# ✅ Preview: https://my-vercel-app-xxx.vercel.app
Step 5: Test the Deployment
# Test static page
curl -s https://my-vercel-app-xxx.vercel.app/ | head -5
# Test API route
curl -s https://my-vercel-app-xxx.vercel.app/api/hello | jq .
# {
# "message": "Hello from Vercel Serverless Function!",
# "timestamp": "2026-03-22T12:00:00.000Z",
# "region": "iad1"
# }
Step 6: Promote to Production
# Deploy directly to production
vercel --prod
# Or promote the preview depVercel incident response procedures with triage, instant rollback, and postmortem.
Vercel Incident Runbook
Overview
Step-by-step incident response for Vercel deployment failures, function errors, and platform outages. Covers rapid triage, instant rollback, communication templates, and postmortem procedures.
Prerequisites
- Access to Vercel dashboard and CLI
- Access to Vercel status page (vercel-status.com)
- Communication channels (Slack, PagerDuty) configured
- Log drain or runtime log access
Instructions
Step 1: Rapid Triage (First 5 Minutes)
# 1. Check if it's a Vercel platform issue
curl -s "https://www.vercel-status.com/api/v2/summary.json" \
| jq '.status.description, [.components[] | select(.status != "operational") | {name, status}]'
# 2. Check current production deployment status
vercel ls --prod
vercel inspect $(vercel ls --prod --json | jq -r '.[0].url')
# 3. Check recent deployments — did a deploy just happen?
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
"https://api.vercel.com/v6/deployments?target=production&limit=5&projectId=prj_xxx" \
| jq '.deployments[] | {uid, state, createdAt: (.createdAt/1000 | todate), url}'
# 4. Check function logs for errors
vercel logs $(vercel ls --prod --json | jq -r '.[0].url') --level=error --limit=20
Step 2: Decision Tree
Is vercel-status.com showing an incident?
├── YES → Vercel platform issue
│ ├── Subscribe to updates on status page
│ ├── Post internal status: "Vercel platform incident — monitoring"
│ └── No action needed from us — wait for Vercel resolution
│
└── NO → Issue is in our deployment
├── Did a deployment happen in the last 30 minutes?
│ ├── YES → Likely deployment regression
│ │ └── ROLLBACK immediately (Step 3)
│ └── NO → Application-level issue
│ ├── Check function logs for new errors
│ ├── Check external dependency status (DB, APIs)
│ └── Investigate and hotfix (Step 4)
│
└── Is the issue region-specific?
├── YES → Check function regions, possible edge issue
└── NO → Global issue, check code and env vars
Step 3: Instant Rollback (< 30 Seconds)
# Option A: Rollback to previous production deployment (fastest)
vercel rollback
# This instantly swaps production traffic — no rebuild needed
# Option B: Rollback to a specific known-good deployment
vercel rollback dpl_xxxxxxxxxxxx
# Option C: Via API (for automation/PagerDuty integration)
curl -X POST "https://api.vercel.com/v9/projects/my-app/promote" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{"deploymentId": "dpl_known_good_id"}'
# Verify rollback succeeded
vercel ls --prod
curl -s https://yourdomain.com/api/health | Install Vercel CLI and configure API token authentication.
Vercel Install & Auth
Overview
Install the Vercel CLI, create a scoped access token, and link your local project to a Vercel project. This skill covers both interactive login and headless CI token authentication via the REST API.
Prerequisites
- Node.js 18+ installed
- npm, pnpm, or yarn available
- A Vercel account (hobby, pro, or enterprise)
Instructions
Step 1: Install Vercel CLI
set -euo pipefail
# Global install (recommended)
npm install -g vercel@latest
# Or project-local
npm install --save-dev vercel@latest
# Verify installation
vercel --version
Step 2: Authenticate — Interactive Login
# Opens browser for OAuth login, stores token in ~/.config/com.vercel.cli
vercel login
# Or login with a specific email
vercel login your@email.com
# Login with GitHub
vercel login --github
# Login with GitLab
vercel login --gitlab
Step 3: Authenticate — Headless Token (CI/CD)
Create a token in the Vercel dashboard at Settings > Tokens or via the API:
# Use a pre-created token — set as environment variable
export VERCEL_TOKEN="your-access-token-here"
# The CLI reads VERCEL_TOKEN automatically — no login needed
vercel whoami
# Output: your-username
# Scope the token to a specific team
export VERCEL_ORG_ID="team_xxxxxxxxxxxx"
export VERCEL_PROJECT_ID="prj_xxxxxxxxxxxx"
Step 4: Link Local Project
# Interactive — walks you through project selection
vercel link
# Or link to a specific project by name
vercel link --project my-project-name
# Verify the link — pulls .vercel/project.json
cat .vercel/project.json
# {"orgId":"team_xxx","projectId":"prj_xxx"}
Step 5: Verify Connection via REST API
# Test token against the REST API directly
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
https://api.vercel.com/v9/projects | jq '.projects[].name'
# List teams
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
https://api.vercel.com/v2/teams | jq '.teams[].name'
Step 6: Pull Environment Variables
# Pull remote env vars to local .env.development.local
vercel env pull .env.development.local
# Pull for a specific environment
vercel env pull --environment=preview
Token Scopes Reference
| Scope | Access | Use Case |
|---|---|---|
| Full Account | All projects, all teams | Personal dev |
| Team-scoped | One team only | Team CI/CD |
| Project-scoped | One project only | Per-project automation |
Identify and avoid Vercel anti-patterns and common integration mistakes.
Vercel Known Pitfalls
Overview
Catalog of the most common Vercel anti-patterns with severity ratings, detection methods, and fixes. Organized by category: secret exposure, serverless function mistakes, edge runtime violations, configuration errors, and cost traps.
Prerequisites
- Access to Vercel codebase for review
- Understanding of Vercel's deployment model
- Familiarity with
vercel-common-errorsfor error codes
Instructions
Category 1: Secret Exposure (Critical)
P1: Secrets in NEXTPUBLIC variables
// BAD — exposed in client JavaScript bundle, visible to anyone
const apiKey = process.env.NEXT_PUBLIC_API_SECRET;
// This value is inlined at build time into the browser bundle
// GOOD — server-only access
const apiKey = process.env.API_SECRET;
// Only accessible in serverless functions and server components
- Detection:
grep -r 'NEXTPUBLIC.SECRET\|NEXTPUBLIC.KEY\|NEXTPUBLIC.*TOKEN' src/ - Fix: Remove
NEXTPUBLICprefix, rotate the exposed secret immediately
P2: Hardcoded credentials in source
// BAD
const client = new Client({ apiKey: 'sk_live_abc123' });
// GOOD
const client = new Client({ apiKey: process.env.API_KEY });
- Detection:
grep -rE 'sklive|sktest|Bearer [a-zA-Z0-9]{20,}' src/ api/ - Fix: Move to environment variables, add pre-commit hook
P3: Secrets in vercel.json
// BAD — vercel.json is committed to git
{
"env": { "API_KEY": "sk_live_abc123" }
}
// GOOD — use Vercel dashboard or CLI
// vercel env add API_KEY production
Category 2: Serverless Function Mistakes (High)
P4: Heavy initialization at module level
// BAD — runs on every cold start, adds 500ms+
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient(); // Connects on import
const cache = await loadLargeDataset(); // Blocks cold start
// GOOD — lazy initialization
let prisma: PrismaClient | null = null;
function getDb() {
if (!prisma) prisma = new PrismaClient();
return prisma;
}
export default async function handler(req, res) {
const db = getDb(); // Only connects on first request
// ...
}
P5: Not returning responses from all code paths
// BAD — some paths don't return, causing NO_RESPONSE_FROM_FUNCTION
export default function handler(req, res) {
if (req.method === 'GET') {
res.json({ data: 'ok' });
}
// POSLoad test and scale Vercel deployments with concurrency tuning and capacity planning.
Vercel Load & Scale
Overview
Load test Vercel deployments to identify scaling limits, cold start impact, and concurrency thresholds. Covers k6/autocannon test scripts, Vercel's auto-scaling model, Fluid Compute concurrency, and capacity planning.
Prerequisites
- Load testing tool: k6, autocannon, or artillery
- Test environment deployment (never load test production without approval)
- Access to Vercel Analytics for monitoring during tests
Instructions
Step 1: Understand Vercel's Scaling Model
Vercel serverless functions scale automatically:
| Behavior | Details |
|---|---|
| Scale-up | New function instances spawn on demand |
| Scale-down | Idle instances shut down after ~15 minutes |
| Cold starts | First request to a new instance pays initialization cost |
| Concurrency | Each instance handles one request at a time (by default) |
| Fluid Compute | Pro/Enterprise: multiple requests per instance |
Concurrency limits by plan:
| Plan | Max Concurrent Functions |
|---|---|
| Hobby | 10 |
| Pro | 1,000 |
| Enterprise | 100,000 |
Step 2: Basic Load Test with autocannon
# Install autocannon
npm install -g autocannon
# Test with 50 concurrent connections for 30 seconds
autocannon -c 50 -d 30 https://my-app-preview.vercel.app/api/endpoint
# Output includes:
# Latency: avg, p50, p99, max
# Requests/sec: avg, min, max
# Errors: timeouts, non-2xx responses
Step 3: k6 Load Test Script
// load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate, Trend } from 'k6/metrics';
const errorRate = new Rate('errors');
const coldStartRate = new Rate('cold_starts');
const latency = new Trend('api_latency');
export const options = {
stages: [
{ duration: '1m', target: 10 }, // Warm up
{ duration: '3m', target: 50 }, // Ramp to 50 users
{ duration: '2m', target: 100 }, // Peak load
{ duration: '1m', target: 0 }, // Cool down
],
thresholds: {
http_req_duration: ['p(95)<2000'], // P95 < 2s
errors: ['rate<0.01'], // Error rate < 1%
},
};
export default function () {
const res = http.get('https://my-app-preview.vercel.app/api/endpoint');
check(res, {
'status is 200': (r) => r.status === 200,
'latency < 2s': (r) => r.timings.duration < 2000,
});
errorRate.add(res.status !== 200);
latency.add(res.timings.duration);
// TConfigure Vercel local development with vercel dev, environment variables, and hot reload.
Vercel Local Dev Loop
Overview
Run Vercel serverless functions and API routes locally using vercel dev. Covers environment variable management, hot reload, local testing patterns, and framework-specific dev servers.
Prerequisites
- Completed
vercel-install-authsetup - Project linked via
vercel link - Node.js 18+ with npm/pnpm
Instructions
Step 1: Pull Environment Variables
# Pull env vars from Vercel to local .env files
vercel env pull .env.development.local
# This creates .env.development.local with all Development-scoped vars:
# VERCEL="1"
# VERCEL_ENV="development"
# DATABASE_URL="postgres://..."
# API_SECRET="sk-..."
Step 2: Start Local Dev Server
# vercel dev starts a local server that emulates the Vercel platform
vercel dev
# Output:
# Vercel CLI 39.x.x — dev command
# > Ready on http://localhost:3000
# With a specific port
vercel dev --listen 8080
# With debug logging
vercel dev --debug
vercel dev provides:
- Serverless function emulation at
/api/*routes - Automatic TypeScript compilation
vercel.jsonrewrites, redirects, and headers applied locally- Environment variables loaded from
.env*.localfiles - Framework detection (Next.js, Nuxt, SvelteKit, etc.)
Step 3: Test Serverless Functions Locally
# Test your API route
curl http://localhost:3000/api/hello
# {"message":"Hello from Vercel Serverless Function!"}
# Test with POST body
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"test","email":"test@example.com"}'
# Test with query parameters
curl "http://localhost:3000/api/search?q=vercel&limit=10"
Step 4: Framework-Specific Dev Servers
For frameworks with their own dev server, use those instead of vercel dev:
# Next.js — built-in Vercel compatibility
npx next dev
# API routes at pages/api/* or app/api/* work identically
# Nuxt
npx nuxi dev
# SvelteKit
npm run dev
# Astro
npx astro dev
The framework dev servers handle API routes natively. Use vercel dev only for plain serverless function projects without a framework.
Step 5: Local Environment Variable Management
# Add a new env var for development only
vercel env add MY_VAR development
# Prompts for value, stores encrypted on Vercel
# List all env vars
vercel env ls
# Remove an env var
vercel env rm MY_VAR development
# Pull updated vars after changes
vercel env pull .env.development.local
Migrate to Vercel from other platforms or re-architecture existing Vercel deployments.
Vercel Migration Deep Dive
Overview
Migrate applications to Vercel from Netlify, AWS (Lambda/CloudFront/S3), Cloudflare Workers, or traditional hosting. Covers configuration mapping, DNS cutover, feature parity validation, and incremental migration with the strangler fig pattern.
Current State
!vercel --version 2>/dev/null || echo 'Vercel CLI not installed'
!cat package.json 2>/dev/null | jq -r '.name // "no package.json"' 2>/dev/null || echo 'N/A'
Prerequisites
- Access to current hosting platform
- Git repository with application source
- DNS management access for domain cutover
- Vercel account (Pro recommended for production)
Instructions
Step 1: Configuration Mapping
From Netlify:
| Netlify | Vercel Equivalent |
|---|---|
netlify.toml |
vercel.json |
redirects / headers |
vercel.json redirects/headers |
Netlify Functions (netlify/functions/) |
API routes (api/) |
| Netlify Edge Functions | Edge Middleware or Edge Functions |
NETLIFY_ENV |
VERCEL_ENV |
| Deploy previews | Preview deployments (automatic) |
| Branch deploys | Branch preview URLs |
// Netlify _redirects → vercel.json
// FROM: /old-page /new-page 301
// TO:
{
"redirects": [
{ "source": "/old-page", "destination": "/new-page", "permanent": true }
]
}
// Netlify _headers → vercel.json
// FROM: /* X-Frame-Options: DENY
// TO:
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "X-Frame-Options", "value": "DENY" }
]
}
]
}
From AWS (Lambda + CloudFront + S3):
| AWS | Vercel Equivalent |
|---|---|
| Lambda functions | Serverless Functions (api/) |
| Lambda@Edge | Edge Functions / Middleware |
| CloudFront distributions | Automatic CDN |
| S3 static hosting | public/ directory |
| API Gateway | Automatic routing |
| CloudFront behaviors | vercel.json rewrites |
| AWS SAM/CDK | vercel.json |
| Secrets Manager | Environment Variables |
// AWS Lambda handler → Vercel Function
// FROM:
export const handlConfigure Vercel across development, preview, and production environments with scoped secrets.
Vercel Multi-Env Setup
Overview
Configure Vercel's three built-in environments (Development, Preview, Production) with scoped environment variables, branch-specific preview URLs, and custom environments for staging. Uses Vercel's native environment system and the REST API for automation.
Prerequisites
- Vercel project linked and deployed
- Separate database instances per environment (recommended)
- Access to Vercel dashboard or VERCEL_TOKEN for API
Instructions
Step 1: Understand Vercel's Environment Model
Vercel provides three built-in environments:
| Environment | Trigger | URL Pattern | Use Case |
|---|---|---|---|
| Production | Push to production branch | yourdomain.com |
Live traffic |
| Preview | Push to any other branch | project-git-branch-team.vercel.app |
PR review |
| Development | vercel dev locally |
localhost:3000 |
Local dev |
Step 2: Scope Environment Variables
# Add a variable scoped to Production only
vercel env add DATABASE_URL production
# Enter: postgres://prod-host:5432/myapp
# Add a variable scoped to Preview only
vercel env add DATABASE_URL preview
# Enter: postgres://staging-host:5432/myapp_staging
# Add a variable scoped to Development only
vercel env add DATABASE_URL development
# Enter: postgres://localhost:5432/myapp_dev
# Add a variable available in ALL environments
vercel env add NEXT_PUBLIC_APP_NAME production preview development
# Enter: My App
# List all env vars with their scopes
vercel env ls
Step 3: Via REST API (Automation)
# Create env vars with specific scoping
curl -X POST "https://api.vercel.com/v9/projects/my-app/env" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"key": "DATABASE_URL",
"value": "postgres://prod-host:5432/myapp",
"type": "encrypted",
"target": ["production"]
}'
# Upsert — update if exists, create if not
curl -X POST "https://api.vercel.com/v9/projects/my-app/env?upsert=true" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"key": "DATABASE_URL",
"value": "postgres://staging-host:5432/myapp_staging",
"type": "encrypted",
"target": ["preview"]
}'
# List all env vars for a project
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
"https://api.vercel.com/v9/projects/my-app/env" \
| jq '.envs[] | Set up Vercel observability with runtime logs, analytics, log drains, and OpenTelemetry tracing.
Vercel Observability
Overview
Configure comprehensive observability for Vercel deployments using built-in analytics, runtime logs, log drains to external providers, OpenTelemetry integration, and custom instrumentation. Covers the full observability stack from function-level metrics to end-user experience monitoring.
Prerequisites
- Vercel Pro or Enterprise plan (for log drains and extended retention)
- External logging provider (Datadog, Axiom, Sentry) — optional
- OpenTelemetry SDK — optional
Instructions
Step 1: Enable Vercel Analytics
In the Vercel dashboard:
- Go to Analytics tab
- Enable Web Analytics (Core Web Vitals, page views)
- Enable Speed Insights (real user performance data)
// For Next.js — add the analytics component
// src/app/layout.tsx
import { Analytics } from '@vercel/analytics/react';
import { SpeedInsights } from '@vercel/speed-insights/next';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Analytics />
<SpeedInsights />
</body>
</html>
);
}
Install: npm install @vercel/analytics @vercel/speed-insights
Step 2: Runtime Logs
# View runtime logs via CLI
vercel logs https://my-app.vercel.app --follow
# Filter by level
vercel logs https://my-app.vercel.app --level=error
# View logs via API
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
"https://api.vercel.com/v2/deployments/dpl_xxx/events?limit=50&direction=backward" \
| jq '.[] | {timestamp: .created, level: .level, message: .text}'
Runtime logs include:
- Function invocation start/end with duration
console.log/warn/erroroutput from functions- Edge Middleware execution logs
- HTTP request/response metadata
Step 3: Structured Logging in Functions
// lib/logger.ts — structured JSON logging
interface LogEntry {
level: 'info' | 'warn' | 'error';
message: string;
requestId?: string;
duration?: number;
[key: string]: unknown;
}
export function log(entry: LogEntry): void {
// Vercel captures console output as runtime logs
const output = JSON.stringify({
...entry,
timestamp: new Date().toISOString(),
region: process.env.VERCEL_REGION,
env: process.env.VERCEL_ENV,
});
switch (entry.level) {
case 'error': console.error(output); break;
case 'warn': console.warn(output); break;
default: console.log(output);
}
}
// Usage in API route:
export async function GET(request: Request) {
const requestId = crypto.randomUUID();
const sOptimize Vercel deployment performance with caching, bundle optimization, and cold start reduction.
Vercel Performance Tuning
Overview
Optimize Vercel deployment performance across four levers: edge caching, bundle size reduction, serverless function cold start elimination, and Core Web Vitals improvement. Uses real Vercel cache headers, ISR, and Edge Functions for maximum performance.
Prerequisites
- Vercel project deployed with accessible URL
- Access to Vercel Analytics (dashboard)
- Bundle analyzer available (
@next/bundle-analyzeror similar)
Instructions
Step 1: Establish Performance Baseline
# Check deployment size and function count
vercel inspect https://my-app.vercel.app
# Run Lighthouse via CLI
npx lighthouse https://my-app.vercel.app --output=json --quiet \
| jq '{performance: .categories.performance.score, lcp: .audits["largest-contentful-paint"].numericValue, cls: .audits["cumulative-layout-shift"].numericValue}'
# Check bundle size (Next.js)
ANALYZE=true npx next build
# Opens bundle analyzer report in browser
Enable Vercel Analytics in the dashboard under Analytics tab for ongoing monitoring.
Step 2: Configure Edge Caching
// api/cached-data.ts — cache API responses at the edge
import type { VercelRequest, VercelResponse } from '@vercel/node';
export default function handler(req: VercelRequest, res: VercelResponse) {
// Cache at Vercel edge for 60s, serve stale for 300s while revalidating
res.setHeader('Cache-Control', 's-maxage=60, stale-while-revalidate=300');
res.json({ data: fetchData(), cachedAt: new Date().toISOString() });
}
// vercel.json — cache static assets aggressively
{
"headers": [
{
"source": "/static/(.*)",
"headers": [
{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }
]
},
{
"source": "/api/public-data",
"headers": [
{ "key": "Cache-Control", "value": "s-maxage=3600, stale-while-revalidate=86400" }
]
}
]
}
Cache header reference:
| Header | Effect | |
|---|---|---|
s-maxage=N |
Cache at Vercel edge for N seconds | |
stale-while-revalidate=N |
Serve stale while revalidating in background | |
max-age=N |
Cache in browser for N seconds | |
immutable |
Never revalidate (use with content-hashed filenames) | |
no-cache |
Always revalidate (edge still caches) | |
no-store |
Never cache anywhere |
| Endpoint Category | Rate Limit |
|---|---|
| Deployments (create) | 100/hour per project |
| Deployments (list/get) | 500/min |
| Projects (CRUD) | 200/min |
| Environment variables | 200/min |
| Domains | 200/min |
| Teams | 200/min |
| DNS records | 200/min |
| General API | 120 requests/min (default) |
Step 2: Implement Retry with Backoff for Vercel API
// lib/rate-limit-handler.ts
interface RateLimitInfo {
limit: number;
remaining: number;
reset: number; // Unix timestamp
}
function parseRateLimitHeaders(headers: Headers): RateLimitInfo {
return {
limit: Number(headers.get('X-RateLimit-Limit') ?? 100),
remaining: Number(headers.get('X-RateLimit-Remaining') ?? 100),
reset: Number(headers.get('X-RateLimit-Reset') ?? 0),
};
}
async function vercelFetchWithRetry(
url: string,
options: RequestInit,
maxRetries = 3
): Promise<Response> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const res = await fetch(url, options);
if (res.status !== 429) return res;
if (attempt === maxRetries) {
throw new Error(`Rate limited after ${maxRetries} retries: ${url}`);
}
// Use Retry-After header if present, otherwise exponential backoff
const retryAfter = res.headers.get('Retry-After');
const waitMs = retryAfter
? Number(retryAfter) * 1000
: Math.min(1000 * Math.pow(2, attempt) + Math.random() * 1000, 30000);
console.warn(`Rate limited (attempt ${attempt + 1}/${maxRetries}). Waiting ${Math.round(waitMs)}ms...`);
await new Promise(r => setTimeout(r, waitMs));
}
throw new Error('Unreachable');
}
Step 3: Proactive Rate Limit Avoidance
// lib/rate-limiter.ts
// Track remaining quota and slow down before hittiImplement a Vercel reference architecture with layered project structure and best practices.
Vercel Reference Architecture
Overview
Implement a production-ready Vercel project architecture with clear separation across edge, server, and client layers. Covers directory structure, middleware patterns, API route organization, shared utilities, and configuration management.
Prerequisites
- Understanding of Vercel's deployment model (edge, serverless, static)
- TypeScript project setup
- Next.js 14+ (recommended) or other Vercel-supported framework
Instructions
Step 1: Directory Structure
my-vercel-app/
├── public/ # Static assets (served from CDN)
│ ├── favicon.ico
│ └── images/
├── src/
│ ├── app/ # Next.js App Router pages
│ │ ├── layout.tsx # Root layout
│ │ ├── page.tsx # Home page
│ │ ├── api/ # API routes (serverless functions)
│ │ │ ├── health/route.ts
│ │ │ ├── users/route.ts
│ │ │ └── webhooks/
│ │ │ └── vercel/route.ts
│ │ ├── dashboard/ # Protected pages
│ │ │ ├── layout.tsx
│ │ │ └── page.tsx
│ │ └── (marketing)/ # Public pages (route group)
│ │ ├── pricing/page.tsx
│ │ └── about/page.tsx
│ ├── lib/ # Shared utilities (server + client)
│ │ ├── api-client.ts # External API wrapper
│ │ ├── db.ts # Database client (lazy singleton)
│ │ ├── env.ts # Typed environment variables
│ │ └── errors.ts # Error classes
│ ├── components/ # React components
│ │ ├── ui/ # Design system primitives
│ │ └── features/ # Feature-specific components
│ └── middleware.ts # Edge Middleware (auth, redirects)
├── vercel.json # Vercel configuration
├── next.config.js # Next.js configuration
├── tsconfig.json
├── package.json
└── .env.example # Required env vars (no values)
Step 2: Typed Environment Variables
// src/lib/env.ts — validate env vars at import time
import { z } from 'zod';
const envSchema = z.object({
DATABASE_URL: z.string().url(),
API_SECRET: z.string().min(16),
NEXT_PUBLIC_API_URL: z.string().url(),
VERCEL_ENV: z.enum(['production', 'preview', 'development']).default('development'),
VERCEL_URL: z.string().optional(),
});
// Fails fast at startup if env vars are missing
export const env = envSchema.parse(process.env);
// Type-safe access throughout the app
// Usage: import { env } from '@/lib/env'; env.DATABASE_URL
Step 3: Database Client (Lazy Singleton)
// src/lib/db.ts — lazy init to minimize cold starts
import { PrismaClient } from '@prisma/client';
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined };Implement reliability patterns for Vercel deployments including circuit breakers, retry logic, and graceful degradation.
Vercel Reliability Patterns
Overview
Build fault-tolerant Vercel deployments with circuit breakers, retry logic, graceful degradation, and instant rollback integration. Addresses reliability at two levels: function-level resilience (protecting against dependency failures) and deployment-level resilience (protecting against bad deploys).
Prerequisites
- Vercel project deployed to production
- Understanding of failure modes in serverless
- External dependencies (databases, APIs) identified
Instructions
Step 1: Circuit Breaker for External Dependencies
// lib/circuit-breaker.ts
type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
class CircuitBreaker {
private state: CircuitState = 'CLOSED';
private failures = 0;
private lastFailure = 0;
private readonly threshold: number;
private readonly resetTimeMs: number;
constructor(threshold = 5, resetTimeMs = 30000) {
this.threshold = threshold;
this.resetTimeMs = resetTimeMs;
}
async call<T>(fn: () => Promise<T>, fallback: () => T): Promise<T> {
if (this.state === 'OPEN') {
if (Date.now() - this.lastFailure > this.resetTimeMs) {
this.state = 'HALF_OPEN';
} else {
console.warn('Circuit OPEN — returning fallback');
return fallback();
}
}
try {
const result = await fn();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
console.error('Circuit breaker caught error:', error);
return fallback();
}
}
private onSuccess(): void {
this.failures = 0;
this.state = 'CLOSED';
}
private onFailure(): void {
this.failures++;
this.lastFailure = Date.now();
if (this.failures >= this.threshold) {
this.state = 'OPEN';
console.warn(`Circuit OPENED after ${this.failures} failures`);
}
}
}
// Usage in a serverless function:
const dbCircuit = new CircuitBreaker(3, 30000);
export default async function handler(req, res) {
const users = await dbCircuit.call(
() => db.user.findMany({ take: 10 }),
() => [] // Fallback: empty array when DB is down
);
res.json({ users, degraded: users.length === 0 });
}
Important for serverless: Circuit breaker state lives in a single function instance. Different instances have independent circuits. For global circuit state, use Vercel KV or Edge Config.
Step 2: Retry with Exponential Backoff
// lib/retry.ts
interface RetryOptions {
maxRetries?: number;
baseDelayMs?: number;
maxDelayMs?: number;
retryOn?: (error: unknown) => boolean;
}
async function withRetry<T>(
fn: () => Promise<T>,
options: RetryOptions = {}
): Promise<T> {
const { maxRetries = 3Production-ready Vercel REST API patterns with typed fetch wrappers and error handling.
Vercel SDK Patterns
Overview
Build a typed, production-ready wrapper around the Vercel REST API (api.vercel.com). Covers authentication, pagination, error handling, retry logic, and common endpoint patterns for deployments, projects, and environment variables.
Prerequisites
- Completed
vercel-install-authsetup - TypeScript project with
strictmode enabled - Vercel access token with appropriate scope
Instructions
Step 1: Create Typed API Client
// lib/vercel-client.ts
interface VercelClientConfig {
token: string;
teamId?: string;
baseUrl?: string;
}
interface VercelError {
error: { code: string; message: string };
}
class VercelClient {
private token: string;
private teamId?: string;
private baseUrl: string;
constructor(config: VercelClientConfig) {
this.token = config.token;
this.teamId = config.teamId;
this.baseUrl = config.baseUrl ?? 'https://api.vercel.com';
}
private async request<T>(
method: string,
path: string,
body?: unknown
): Promise<T> {
const url = new URL(path, this.baseUrl);
if (this.teamId) url.searchParams.set('teamId', this.teamId);
const res = await fetch(url.toString(), {
method,
headers: {
Authorization: `Bearer ${this.token}`,
'Content-Type': 'application/json',
},
body: body ? JSON.stringify(body) : undefined,
});
if (!res.ok) {
const err: VercelError = await res.json();
throw new VercelApiError(res.status, err.error.code, err.error.message);
}
// 204 No Content
if (res.status === 204) return undefined as T;
return res.json() as Promise<T>;
}
// --- Projects ---
async listProjects(limit = 20) {
return this.request<{ projects: VercelProject[] }>(
'GET', `/v9/projects?limit=${limit}`
);
}
async getProject(idOrName: string) {
return this.request<VercelProject>('GET', `/v9/projects/${idOrName}`);
}
// --- Deployments ---
async listDeployments(projectId?: string, limit = 20) {
const params = new URLSearchParams({ limit: String(limit) });
if (projectId) params.set('projectId', projectId);
return this.request<{ deployments: VercelDeployment[] }>(
'GET', `/v6/deployments?${params}`
);
}
async getDeployment(idOrUrl: string) {
return this.request<VercelDeployment>(
'GET', `/v13/deployments/${idOrUrl}`
);
}
// --- Environment Variables ---
async listEnvVars(projectId: string) {
return this.request<{ envs: VercelEnvVar[] }>(
'GET', `/v9/projects/${projectId}/env`
);
}
async createEnvVar(projectId: string, envVar: CreateEnvVarInput) {
return this.request<VercelEnvVar>(
'POST', `/v9/projects/$Apply Vercel security best practices for secrets, headers, and access control.
Vercel Security Basics
Overview
Secure Vercel deployments with proper secret management, security headers, deployment protection, and access token hygiene. Covers environment variable scoping, Content Security Policy, and preventing common secret exposure patterns.
Prerequisites
- Vercel CLI installed and authenticated
- Access to Vercel dashboard
- Understanding of HTTP security headers
Instructions
Step 1: Secret Management with Environment Variables
# Add secrets scoped to specific environments
vercel env add DATABASE_URL production
vercel env add DATABASE_URL preview
vercel env add DATABASE_URL development
# Use 'sensitive' type — values hidden in dashboard and logs
vercel env add API_SECRET production --sensitive
# Via REST API
curl -X POST "https://api.vercel.com/v9/projects/my-app/env" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"key": "API_SECRET",
"value": "sk-secret-value",
"type": "sensitive",
"target": ["production"]
}'
Critical rule: Never prefix secrets with NEXTPUBLIC. Variables starting with NEXTPUBLIC are inlined into the client JavaScript bundle and visible to anyone.
Step 2: Security Headers via vercel.json
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "X-Frame-Options", "value": "DENY" },
{ "key": "X-XSS-Protection", "value": "1; mode=block" },
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
{ "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" },
{
"key": "Strict-Transport-Security",
"value": "max-age=63072000; includeSubDomains; preload"
},
{
"key": "Content-Security-Policy",
"value": "default-src 'self'; script-src 'self' 'unsafe-inline' https://vercel.live; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.vercel.com"
}
]
}
]
}
Step 3: Security Headers via Edge Middleware
// middleware.ts
import { NextResponse } from 'Upgrade Vercel CLI, Node.
Vercel Upgrade Migration
Overview
Safely upgrade Vercel CLI, Node.js runtime versions, and framework versions (especially Next.js) on Vercel. Covers breaking change detection, vercel.json schema changes, and rollback strategy.
Current State
!vercel --version 2>/dev/null || echo 'Vercel CLI not installed'
!node --version 2>/dev/null || echo 'N/A'
!cat package.json 2>/dev/null | jq -r '.dependencies.next // "no next.js"' 2>/dev/null || echo 'N/A'
Prerequisites
- Current Vercel CLI installed
- Git for version control
- Test suite available
- Preview deployment for testing
Instructions
Step 1: Check Current Versions
# Current CLI version
vercel --version
# Current Node.js runtime on Vercel
cat package.json | jq '.engines.node'
# Or check vercel.json
cat vercel.json | jq '.functions'
# Check for available CLI updates
npm outdated -g vercel
# Check framework version
npm ls next react
Step 2: Upgrade Vercel CLI
# Upgrade to latest
npm install -g vercel@latest
# Or specific version
npm install -g vercel@39
# Verify
vercel --version
CLI breaking changes to watch for:
- v28+:
vercel env pulloutput format changed - v32+:
vercel devuses new function runtime - v37+:
vercel.jsonbuildsproperty deprecated in favor of framework detection
Step 3: Upgrade Node.js Runtime
// package.json — specify the Node.js version
{
"engines": {
"node": "20.x"
}
}
Available runtimes on Vercel:
| Runtime | Status | EOL |
|---|---|---|
| Node.js 18.x | Supported | April 2025 |
| Node.js 20.x | Active LTS (recommended) | April 2026 |
| Node.js 22.x | Current | October 2027 |
# Test locally with the target Node version first
nvm use 20
npm test
npm run build
Step 4: Upgrade Next.js on Vercel
# Use the Next.js upgrade codemod
npx @next/codemod@latest upgrade
# Or manual upgrade
npm install next@latest react@latest react-dom@latest
# Check for breaking changes
npx @next/codemod --dry-run
Key Next.js migration points:
- 13 → 14: App Router stable, Turbopack available, Server Actions stable
- 14 → 15:
fetchno longer cached by default,cookies()is async,NextRequest.georemoved (usegeolocation()from@vercel/functions)
Implement Vercel webhook handling with signature verification and event processing.
Vercel Webhooks & Events
Overview
Handle Vercel webhook events (deployment.created, deployment.ready, deployment.error) with HMAC signature verification. Covers both integration webhooks (Vercel Marketplace) and project-level deploy hooks.
Prerequisites
- HTTPS endpoint accessible from the internet
- Webhook secret from Vercel dashboard or integration settings
cryptomodule for HMAC signature verification
Instructions
Step 1: Register a Webhook
In the Vercel dashboard:
- Go to Settings > Webhooks
- Add your endpoint URL (must be HTTPS)
- Select events to subscribe to
- Copy the webhook secret for signature verification
Or for Integration webhooks, configure in the Integration Console at vercel.com/dashboard/integrations.
Step 2: Verify Webhook Signature
// api/webhooks/vercel.ts
import type { VercelRequest, VercelResponse } from '@vercel/node';
import crypto from 'crypto';
const WEBHOOK_SECRET = process.env.VERCEL_WEBHOOK_SECRET!;
function verifySignature(body: string, signature: string): boolean {
const expectedSignature = crypto
.createHmac('sha1', WEBHOOK_SECRET)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
export default async function handler(req: VercelRequest, res: VercelResponse) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
// Get raw body for signature verification
const rawBody = JSON.stringify(req.body);
const signature = req.headers['x-vercel-signature'] as string;
if (!signature || !verifySignature(rawBody, signature)) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process the event
const event = req.body;
await handleEvent(event);
res.status(200).json({ received: true });
}
Step 3: Handle Deployment Events
// lib/webhook-handlers.ts
interface VercelWebhookEvent {
id: string;
type: string;
createdAt: number;
payload: {
deployment: {
id: string;
name: string;
url: string;
meta: Record<string, string>;
};
project: {
id: string;
name: string;
};
target: 'production' | 'preview' | null;
user: { id: string; email: string; username: string };
};
}
async function handleEvent(event: VercelWebhookEvent): Promise<void> {
switch (event.type) {
case 'deployment.created':
console.log(`Deployment started: ${event.payload.deployment.url}`);
// Notify Slack, update status board, etc.
break;
case 'deployment.ready':
console.log(`Deployment ready: ${event.pReady to use vercel-pack?
Related Plugins
ansible-playbook-creator
Create Ansible playbooks for configuration management
auto-scaling-configurator
Configure auto-scaling policies for applications and infrastructure
backup-strategy-implementor
Implement backup strategies for databases and applications
ci-cd-pipeline-builder
Build CI/CD pipelines for GitHub Actions, GitLab CI, Jenkins, and more
cloud-cost-optimizer
Optimize cloud costs and generate cost reports
compliance-checker
Check infrastructure compliance (SOC2, HIPAA, PCI-DSS)