Vercel Integration Guide
Where does my code run?
Static → ISR → Edge-SSR → Node-SSR, with Suspense/streaming layered on either SSR.
App-router rendering is decided per-segment by what you `await` and which dynamic APIs you touch (`cookies()`, `headers()`, `searchParams`). On Vercel, default to the Node.js runtime on Fluid Compute — instance reuse cuts cold starts, you keep full Node APIs, and it streams and even holds WebSockets. The Edge runtime is now legacy (Vercel no longer recommends it; middleware and former Edge Functions run on Vercel Functions under the hood). ISR is the sweet spot for content that's mostly read but occasionally written — use `revalidateTag()` over hard TTLs once your data model fits. Streaming + RSC lets the page shell paint fast while slow data resolves underneath, which often makes “but I need personalisation” not actually require a heavier per-request render.
Five rendering strategies
Same Next.js project can mix all five — one per route. Tap a card for the trade-offs.
Pick a strategy by asking four questions
Flip the toggles for one route at a time. The recommendation underneath updates to whichever strategy fits the smallest set of guarantees you actually need — overshooting costs TTFB and money.
Generated at build time; served globally from CDN.
Why this one: SEO-critical, content rarely changes → pre-render once, serve from every edge.
Heuristics, not laws. Real apps mix strategies per route — your marketing pages can be Static while your dashboard is Edge-SSR, all in the same Next.js project. The chooser exists to break the “just SSR everything” reflex.
The most common mistake: over-rendering. If a route only needs cookies + a fast database call, Streaming (or a mostly-static shell) usually covers it — and the old reflex of reaching for the Edge runtime is now legacy, since Fluid Compute gives Node low cold starts on its own.
██╗ ██╗███████╗██████╗ ██████╗███████╗██╗
██║ ██║██╔════╝██╔══██╗██╔════╝██╔════╝██║
██║ ██║█████╗ ██████╔╝██║ █████╗ ██║
╚██╗ ██╔╝██╔══╝ ██╔══██╗██║ ██╔══╝ ██║
╚████╔╝ ███████╗██║ ██║╚██████╗███████╗███████╗
╚═══╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝╚══════╝╚══════╝Vercel Integration Guide
Focus: Deploying, inspecting, and automating Vercel projects from inside Claude Code using the official Vercel MCP server and Vercel CLI.
Overview
Vercel is a full compute platform — not just a frontend/static host. It runs full backend frameworks (Express, FastAPI, NestJS, Hono, …) natively with zero config, and its default runtime is Fluid Compute (regular Node.js with instance reuse), which replaced the old push toward the Edge runtime. Its official MCP server gives Claude Code direct access to deployments, logs, runtime errors, projects, Web Analytics, and domains — no browser required. Combined with the vercel CLI and GitHub Actions, you can build fully automated deploy, preview, and rollback pipelines driven by Claude Code.
Here is the core flow at a glance — a single git push fans out into builds, previews, and a production deploy on the edge:
Official Documentation
| Resource | URL |
|---|---|
| Vercel Docs | https://vercel.com/docs |
| Vercel MCP Server | https://vercel.com/docs/agent-resources/vercel-mcp |
| Vercel CLI Reference | https://vercel.com/docs/cli |
| REST API | https://vercel.com/docs/rest-api |
| Next.js Docs | https://nextjs.org/docs |
MCP Server Setup
Official Vercel MCP Server (Remote, Recommended)
Vercel hosts an official MCP server at https://mcp.vercel.com using OAuth authentication (it implements the current MCP Authorization + Streamable HTTP specs).
# Add Vercel MCP to Claude Code (authenticates via OAuth browser flow)
claude mcp add --transport http vercel https://mcp.vercel.com
# then, inside `claude`, authorize the connection:
/mcpClaude Code will open a browser to complete OAuth. Once done, the token is cached automatically. To wire the same server into every installed agent at once, Vercel also ships a one-shot installer: npx -y add-mcp https://mcp.vercel.com -g.
.mcp.json Configuration (Token-based)
{
"mcpServers": {
"vercel": {
"type": "http",
"url": "https://mcp.vercel.com",
"headers": {
"Authorization": "Bearer ${VERCEL_TOKEN}"
}
}
}
}Available MCP Tools
The tool set has grown well beyond deploy inspection. Core tools you will reach for:
| Tool | Description |
|---|---|
search_vercel_documentation | Search Vercel docs in natural language |
list_teams | List your Vercel teams |
list_projects / get_project | List projects; get framework, domains, latest deploy |
list_deployments / get_deployment | List deployments; get status and URLs |
get_deployment_build_logs | Fetch build logs (errorsOnly to isolate failures) |
get_runtime_logs | Fetch function runtime logs with filters/full-text search |
get_runtime_errors | Grouped production error clusters — start here before get_runtime_logs |
deploy_to_vercel | Deploy a supplied file tree to preview or production |
get_web_analytics | Query visitors, page views, and custom events |
check_domain_availability_and_price / buy_domain | Check and purchase domains |
use_vercel_cli | Run Vercel CLI commands through the server |
Additional categories exist: Agent Runs observability (list_agent_runs, get_agent_run, get_agent_run_trace — for eve agents), Purchase (buy_pro, buy_credits, buy_addon), Access (web_fetch_vercel_url), Design import, and Toolbar threads. See the tools reference for the full, current list.
CLI Integration
Installation
npm install -g vercelAuthentication
vercel login
# Or use a token:
vercel login --token $VERCEL_TOKENKey Commands
# Deploy current directory
vercel deploy
# Deploy to production
vercel --prod
# List deployments
vercel ls
# Inspect a deployment
vercel inspect <deployment-url>
# View logs
vercel logs <deployment-url>
# Manage environment variables
vercel env add MY_VAR production
vercel env ls production
vercel env rm MY_VAR production
# Rollback to previous deployment
vercel rollback
# Pull env vars to local .env
vercel env pull .env.local
# Link project to local directory
vercel link
# Open project dashboard in browser
vercel openEnvironment Variables
# Vercel token (from vercel.com/account/tokens)
VERCEL_TOKEN=...
# Project and team (from project settings or `vercel link`)
VERCEL_ORG_ID=team_...
VERCEL_PROJECT_ID=prj_...
# Used inside deployed functions
NEXT_PUBLIC_API_URL=https://api.example.com
DATABASE_URL=postgresql://...Sync local .env.local with Vercel:
vercel env pull .env.localCompute model — Fluid Compute (default)
Since April 2025 Fluid Compute is the default runtime for new projects, and it changes several long-held assumptions. It reuses a single function instance across concurrent requests (fewer cold starts), keeps the full Node.js API surface, and bills on Active CPU — you pay for CPU time while your code executes, plus provisioned memory and invocations, not wall-clock GB-seconds. Enable it explicitly with "fluid": true in the config file if a project predates the default.
What this means in practice (correct these if you learned Vercel a year ago):
- The Edge runtime is legacy. Vercel no longer recommends
export const runtime = 'edge'; middleware and former Edge Functions now run on Vercel Functions under the hood. Stay on Node.js (Fluid) unless you have a specific reason not to. - Node.js 24 LTS is the current default (Node 18 is deprecated). Bun, Python 3.13/3.14, and Rust are also supported runtimes.
- Streaming and SSE are not Edge-exclusive.
ReadableStream, Server-Sent Events (text/event-stream), and AI token streaming all work on the default Node.js runtime with zero config. - Functions support WebSockets. With Fluid Compute a function can hold an open bidirectional WebSocket — no separate socket server, Pusher, or Ably needed. Next.js uses
experimental_upgradeWebSocket()from@vercel/functions. - Bigger limits: up to 5 GB package size (was 250 MB) and 100 MB request bodies (was 4.5 MB) — enough for Playwright, Python AI libs, and large upload/webhook routes directly on Functions.
- Durations: default 300 s on every plan; Pro/Enterprise max 800 s (GA), extended 1800 s / 30 min in beta on Node 20/22/24 and Python 3.12–3.14. For unbounded, pause/resume work use Vercel Workflows instead.
Vercel PostgresandVercel KVare retired — provision databases through the Vercel Marketplace (Neon, Supabase, Upstash, etc.). codeAmani already standardizes on Supabase/Neon, so this is a naming change, not a migration.
codeAmani angle: because a Fluid Node.js function can now hold persistent connections and stream, you no longer need to route realtime/long-lived work off-platform by reflex. It also unlocks AI Gateway (one API across providers with fallbacks), Queues (durable event streaming), and Sandbox (isolated code execution) for AI features.
Project Configuration — vercel.ts (recommended) and vercel.json
Project configuration lives at the repo root and controls rewrites, redirects, response headers, per-function compute (region, runtime, maxDuration), Fluid Compute, and scheduled crons. Settings here are committed to git and apply on every deploy, so they are the durable counterpart to anything you can also click in the dashboard.
vercel.ts is now the recommended format. It replaces vercel.json with full TypeScript — typed config, helper functions, dynamic logic, and access to deployment-time env vars. Install @vercel/config and export a typed config:
// vercel.ts
import { routes, deploymentEnv, type VercelConfig } from '@vercel/config/v1';
export const config: VercelConfig = {
buildCommand: 'npm run build',
framework: 'nextjs',
rewrites: [
// front an external API under your own domain
routes.rewrite('/api/proxy/(.*)', 'https://api.example.com/$1', {
requestHeaders: { authorization: `Bearer ${deploymentEnv('API_TOKEN')}` },
}),
],
redirects: [
routes.redirect('/old-pricing', '/pricing', { permanent: true }),
],
headers: [
routes.header('/(.*)', [
{ key: 'X-Frame-Options', value: 'SAMEORIGIN' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
]),
routes.cacheControl('/static/(.*)', { public: true, maxAge: '1 week', immutable: true }),
],
crons: [
{ path: '/api/reconcile-mpesa', schedule: '0 * * * *' },
],
};Install: npm i @vercel/config. The routes.* helpers (rewrite, redirect, header, cacheControl) build the same route objects vercel.json uses, and deploymentEnv('NAME') injects an env var at deploy time. Import from @vercel/config/v1 to pin the schema.
vercel.json (still fully supported)
vercel.json remains valid and is what most existing projects (including this dashboard) use. Start the file with the $schema line for editor autocomplete and validation.
How a request and a scheduled job flow through it:
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"redirects": [
{ "source": "/old-pricing", "destination": "/pricing", "permanent": true }
],
"rewrites": [
{ "source": "/api/proxy/:path*", "destination": "https://api.example.com/:path*" }
],
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "X-Frame-Options", "value": "SAMEORIGIN" },
{ "key": "X-Content-Type-Options", "value": "nosniff" }
]
}
],
"functions": {
"app/api/mpesa/stk/route.ts": {
"maxDuration": 30
}
},
"crons": [
{ "path": "/api/reconcile-mpesa", "schedule": "0 * * * *" }
]
}Field notes (verified against the current schema):
redirects— use"permanent": truefor 301/308,falsefor 307.source/destinationsupport:paramand:path*patterns.rewrites— proxy without changing the visible URL; great for fronting an external API under your own domain.functions— keys are file globs (e.g.app/api/*/route.ts). SetmaxDuration(seconds) andruntime. Routes with different settings are bundled separately. Under Fluid Compute, memory/CPU is a CPU type (Standard/Performance) set in the dashboard, not amemory(MB) number in the file.fluid— top-level"fluid": trueopts a project into Fluid Compute if it predates the April 2025 default.regions— set a top-level"regions": ["fra1"]to pin functions to a region. For Kenyan / East African users,fra1(Frankfurt) is the lowest-latency Vercel region; the defaultiad1(US East) adds a costly round trip.crons— each entry needs apath(starting with/) and a standard 5-fieldscheduleexpression.
Gotcha — secure your cron endpoints. Cron paths are publicly reachable URLs; anyone who guesses /api/reconcile-mpesa can trigger your job. Vercel sends an Authorization: Bearer <CRON_SECRET> header on scheduled invocations — set a CRON_SECRET env var and reject any request whose header does not match:
// app/api/reconcile-mpesa/route.ts
export function GET(request: Request) {
const authHeader = request.headers.get('authorization');
if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
return new Response('Unauthorized', { status: 401 });
}
// ... reconciliation logic
return Response.json({ ok: true });
}Second gotcha: under Fluid Compute (the default) there is no
memory(MB) field — pick a CPU type (Standard/Performance) in the project dashboard instead.maxDuration,regions, andfluidstill work in the file (and invercel.ts).
Automation Workflows
You are in great shape to automate the full loop — here is how Claude Code drives a deploy with the CLI and then inspects the result through the MCP server:
Claude Code Hook: Post-Deploy Notification
.claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "if echo \"$CLAUDE_TOOL_OUTPUT\" | grep -q 'vercel --prod'; then node scripts/notify-deploy.js; fi"
}
]
}
]
}
}Slash Command: Deploy and Inspect
.claude/commands/deploy.md:
Deploy the current project to Vercel production and report the deployment URL and status.
Use Bash to run:
```bash
vercel --prod --yes 2>&1 | tail -5Then use the Vercel MCP tool list_deployments to get the latest deployment's URL and build status. Report back with the deployment URL, status, and any build warnings.
Usage: `/project:deploy`
### CI/CD: GitHub Actions with Vercel
```yaml
# .github/workflows/deploy.yml
name: Deploy to Vercel
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Vercel CLI
run: npm install -g vercel
- name: Pull Vercel environment
run: vercel env pull .env.production --token=${{ secrets.VERCEL_TOKEN }}
- name: Build
run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy
id: deploy
run: |
url=$(vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }})
echo "url=$url" >> $GITHUB_OUTPUT
- 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: `Deployed to: ${{ steps.deploy.outputs.url }}`
})Preview Deployments per Branch
# Deploy a preview for the current branch
vercel deploy --env BRANCH=$(git branch --show-current)Common Use Cases
| Use Case | Approach |
|---|---|
| Inspect failing build | MCP get_deployment_build_logs (errorsOnly) |
| Triage production errors | MCP get_runtime_errors first, then get_runtime_logs to drill in |
| Rollback bad release | vercel rollback or MCP |
| Manage env vars | vercel env add/ls/rm |
| Domain assignment | MCP check_domain_availability_and_price / buy_domain |
| Preview links in PRs | GitHub Actions + vercel deploy |
| Realtime / streaming / WebSockets | Fluid Node.js function (no separate socket server) |
| Multi-provider AI with fallbacks | Vercel AI Gateway |
| Long-running / durable jobs | Vercel Workflows (unbounded) or Queues (durable events) |
Troubleshooting
| Issue | Fix |
|---|---|
vercel: command not found | npm install -g vercel |
| OAuth timeout | Use VERCEL_TOKEN in .mcp.json instead |
| Build failing | Use MCP get_deployment_build_logs to read errors |
| Env vars missing in prod | Run vercel env ls production to verify |
VERCEL_PROJECT_ID unknown | Run vercel link in project root |