← Back to dashboard

Vercel Integration Guide

Where does my code run?

The real model

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.

Rendering-strategy chooserrecommendation: Static
StaticTTFB ~30 ms · 100% edge

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.

Text
██╗   ██╗███████╗██████╗  ██████╗███████╗██╗
██║   ██║██╔════╝██╔══██╗██╔════╝██╔════╝██║
██║   ██║█████╗  ██████╔╝██║     █████╗  ██║
╚██╗ ██╔╝██╔══╝  ██╔══██╗██║     ██╔══╝  ██║
 ╚████╔╝ ███████╗██║  ██║╚██████╗███████╗███████╗
  ╚═══╝  ╚══════╝╚═╝  ╚═╝ ╚═════╝╚══════╝╚══════╝

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


MCP Server Setup

Vercel hosts an official MCP server at https://mcp.vercel.com using OAuth authentication (it implements the current MCP Authorization + Streamable HTTP specs).

Bash
# 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:
/mcp

Claude 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)

JSON
{
  "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:

ToolDescription
search_vercel_documentationSearch Vercel docs in natural language
list_teamsList your Vercel teams
list_projects / get_projectList projects; get framework, domains, latest deploy
list_deployments / get_deploymentList deployments; get status and URLs
get_deployment_build_logsFetch build logs (errorsOnly to isolate failures)
get_runtime_logsFetch function runtime logs with filters/full-text search
get_runtime_errorsGrouped production error clusters — start here before get_runtime_logs
deploy_to_vercelDeploy a supplied file tree to preview or production
get_web_analyticsQuery visitors, page views, and custom events
check_domain_availability_and_price / buy_domainCheck and purchase domains
use_vercel_cliRun 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

Bash
npm install -g vercel

Authentication

Bash
vercel login
# Or use a token:
vercel login --token $VERCEL_TOKEN

Key Commands

Bash
# 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 open

Environment Variables

Bash
# 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:

Bash
vercel env pull .env.local

Compute 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 Postgres and Vercel KV are 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 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:

TypeScript
// 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:

JSON
{
  "$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": true for 301/308, false for 307. source/destination support :param and :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). Set maxDuration (seconds) and runtime. Routes with different settings are bundled separately. Under Fluid Compute, memory/CPU is a CPU type (Standard/Performance) set in the dashboard, not a memory (MB) number in the file.
  • fluid — top-level "fluid": true opts 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 default iad1 (US East) adds a costly round trip.
  • crons — each entry needs a path (starting with /) and a standard 5-field schedule expression.

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:

TypeScript
// 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, and fluid still work in the file (and in vercel.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:

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:

Markdown
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 -5

Then 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.

Text

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

Bash
# Deploy a preview for the current branch
vercel deploy --env BRANCH=$(git branch --show-current)

Common Use Cases

Use CaseApproach
Inspect failing buildMCP get_deployment_build_logs (errorsOnly)
Triage production errorsMCP get_runtime_errors first, then get_runtime_logs to drill in
Rollback bad releasevercel rollback or MCP
Manage env varsvercel env add/ls/rm
Domain assignmentMCP check_domain_availability_and_price / buy_domain
Preview links in PRsGitHub Actions + vercel deploy
Realtime / streaming / WebSocketsFluid Node.js function (no separate socket server)
Multi-provider AI with fallbacksVercel AI Gateway
Long-running / durable jobsVercel Workflows (unbounded) or Queues (durable events)

Troubleshooting

IssueFix
vercel: command not foundnpm install -g vercel
OAuth timeoutUse VERCEL_TOKEN in .mcp.json instead
Build failingUse MCP get_deployment_build_logs to read errors
Env vars missing in prodRun vercel env ls production to verify
VERCEL_PROJECT_ID unknownRun vercel link in project root