src/skills/infra-platform-vercel/SKILL.md
Vercel deployment platform — project configuration, serverless/edge functions, Routing Middleware, cron jobs, environment variables, monorepo setup
npx skillsauth add agents-inc/skills infra-platform-vercelInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Quick Guide: Configure deployments with
vercel.json(static) orvercel.ts(programmatic, build-time). Functions default to Node.js runtime iniad1region. Useexport const runtime = 'edge'for edge functions (V8 isolates, global deployment). Routing Middleware runs before the cache globally. Secure cron jobs withCRON_SECRET. Enable Fluid compute for better concurrency and cost. Always place functions near your data source.
<critical_requirements>
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST always include "$schema": "https://openapi.vercel.sh/vercel.json" in vercel.json for IDE validation)
(You MUST place functions in a region close to your data source -- the default iad1 may add latency if your database is elsewhere)
(You MUST verify CRON_SECRET in cron job handlers -- Vercel cron endpoints are publicly accessible URLs)
(You MUST design cron jobs to be idempotent -- Vercel may deliver the same cron event more than once)
(You MUST NOT store secrets in vercel.json or source code -- use Environment Variables in the Vercel dashboard)
</critical_requirements>
Auto-detection: Vercel, vercel.json, vercel.ts, @vercel/config, Vercel Functions, Vercel deploy, VERCEL_URL, VERCEL_ENV, VERCEL_REGION, Routing Middleware, middleware.ts, Edge Runtime, export const runtime, Fluid compute, vercel cron, cron jobs vercel, vercel.json crons, vercel dev, vercel build, vercel deploy, vercel env, vercel link, vercel pull, .vercelignore, vercel monorepo, vercel regions, vercel headers, vercel redirects, vercel rewrites
When to use:
vercel.json or vercel.tsWhen NOT to use:
Key patterns covered:
vercel.json / vercel.ts project configuration with IDE schema validationCRON_SECRET authenticationhas/missing)VERCEL_ENV, VERCEL_URL, VERCEL_REGION)Vercel is a deployment platform that auto-detects your framework and optimizes builds, routing, and function deployment. The key architectural principle: configure only what you need to override. Vercel's defaults are sensible for most projects -- vercel.json exists for when those defaults don't fit.
iad1 (Washington, D.C.). If your database is in Europe, set regions to a European region.When to use Vercel:
When NOT to use Vercel:
Every Vercel project can have a vercel.json at the root for static configuration, or vercel.ts for programmatic build-time configuration. Always include the $schema for IDE autocompletion.
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"regions": ["iad1"],
"functions": {
"api/**/*.ts": {
"maxDuration": 30
}
},
"crons": [
{
"path": "/api/daily-cleanup",
"schedule": "0 2 * * *"
}
]
}
Why good: Schema enables IDE validation, regions explicit about function placement, maxDuration prevents runaway functions, cron declared in config alongside deployment
See examples/core.md for complete configuration with all properties.
Functions in the api/ directory are automatically deployed. The recommended signature uses the fetch handler. Node.js is the default runtime.
// api/users.ts -- Node.js runtime (default)
export default {
async fetch(request: Request) {
const url = new URL(request.url);
const id = url.searchParams.get("id");
if (!id) {
return Response.json({ error: "Missing id" }, { status: 400 });
}
// Your data fetching logic here
return Response.json({ id, name: "Example User" });
},
};
Why good: Uses Web Standard fetch signature (works across runtimes), Response.json for typed responses, proper error handling with status codes
See examples/core.md for function configuration, streaming, and runtime selection.
Edge functions run on V8 isolates globally, closest to the user. Use for latency-sensitive operations with limited API needs. Vercel now recommends Node.js for most use cases due to Fluid compute improvements.
// api/geo.ts -- Edge runtime
export const runtime = "edge";
export default {
async fetch(request: Request) {
const country = request.headers.get("x-vercel-ip-country") ?? "US";
return Response.json({ country, region: process.env.VERCEL_REGION });
},
};
When to use: Latency-critical responses, geo-routing, simple request/response transformations
When not to use: Heavy computation, Node.js-only APIs (fs, child_process), large dependencies (1-4 MB code size limit)
See examples/core.md for Edge vs Node.js comparison and limitations.
Routing Middleware executes before the cache on every request. Create a middleware.ts file at the project root. Default runtime is Edge but can be changed to Node.js.
// middleware.ts -- runs before every request
export default function middleware(request: Request) {
const url = new URL(request.url);
// Redirect old paths
if (url.pathname === "/old-page") {
return new Response(null, {
status: 302,
headers: { Location: "/new-page" },
});
}
}
// Optional: change runtime from Edge (default) to Node.js
export const config = {
runtime: "nodejs",
};
Why good: Runs globally before cache, can personalize static content, supports auth checks, geo-routing, A/B testing
Limits: 50ms average CPU time on Edge runtime, 4 MB max request body, 14 KB max URL length
See examples/routing.md for auth, geo-routing, and conditional middleware patterns.
Define scheduled functions in vercel.json. Cron endpoints are regular API routes -- secure them with CRON_SECRET.
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"crons": [
{
"path": "/api/cron/cleanup",
"schedule": "0 2 * * *"
}
]
}
// api/cron/cleanup.ts
export default {
async fetch(request: Request) {
const authHeader = request.headers.get("authorization");
if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
return new Response("Unauthorized", { status: 401 });
}
// Your scheduled task logic here (must be idempotent)
return Response.json({ success: true });
},
};
Why good: CRON_SECRET verification prevents unauthorized invocation, idempotent design handles duplicate delivery, simple cron expression syntax
Gotcha: Crons only run on Production deployments, not Preview. Vercel may deliver events more than once.
See examples/cron-jobs.md for schedule expressions and handler patterns.
Configure routing rules in vercel.json with optional has/missing conditions for matching request properties.
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "X-Frame-Options", "value": "DENY" }
]
}
],
"redirects": [
{
"source": "/blog/:slug",
"destination": "/posts/:slug",
"permanent": true
}
],
"rewrites": [
{ "source": "/api/:path*", "destination": "https://api.example.com/:path*" }
]
}
Why good: Declarative routing rules applied at the CDN layer (fast), pattern matching with named segments (:slug, :path*), conditional matching with has/missing
See examples/routing.md for geo-based redirects, conditional headers, and rewrite patterns.
Vercel provides built-in environment variables and supports custom ones via the dashboard. Access framework-agnostic variables via process.env.
// Built-in environment variables
const DEPLOYMENT_ENV = process.env.VERCEL_ENV; // "production" | "preview" | "development"
const DEPLOYMENT_URL = process.env.VERCEL_URL; // e.g., "my-app-abc123.vercel.app"
const FUNCTION_REGION = process.env.VERCEL_REGION; // e.g., "iad1"
const GIT_COMMIT_SHA = process.env.VERCEL_GIT_COMMIT_SHA;
Gotcha: VERCEL_URL does not include the protocol (https://). Always prepend it: `https://${process.env.VERCEL_URL}`
See examples/core.md for environment variable scoping and CRON_SECRET setup.
Vercel supports monorepos by setting the Root Directory per project. Use ignoreCommand to skip builds when the relevant app hasn't changed.
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"ignoreCommand": "git diff --quiet HEAD^ HEAD ./",
"buildCommand": "pnpm --filter my-app build",
"installCommand": "pnpm install"
}
Key setup: In the Vercel dashboard, set Root Directory to apps/my-app (or wherever the app lives). Vercel CLI should always be run from the monorepo root.
See examples/monorepo.md for monorepo setup, Nx integration, custom ignore patterns, and vercel.ts programmatic config.
</patterns>| Setting | Purpose | When to use |
| ------------------------- | --------------------------------------- | -------------------------------------------- |
| regions: ["iad1"] | Deploy to specific region(s) | When your data source is in a known region |
| functionFailoverRegions | Failover during outages | Enterprise plan, critical APIs |
| fluid: true | Reuse instances for concurrent requests | Default for new projects since April 2025 |
| Per-function regions | Different regions per function | When functions access different data sources |
For runtime comparison and plan limits, see reference.md.
</performance><decision_framework>
What does your function need?
|
+-- Full Node.js APIs (fs, child_process, native modules)?
| --> Node.js runtime
|
+-- Global low-latency, minimal dependencies?
| --> Edge runtime (but consider Node.js + multi-region)
|
+-- Heavy computation or large dependencies?
| --> Node.js runtime (250 MB limit vs 1-4 MB Edge)
|
+-- Not sure?
--> Node.js (default, recommended by Vercel for most cases)
Does it need to run before every request (auth, redirects)?
|
+-- YES --> Routing Middleware (middleware.ts)
|
+-- NO --> Is it a scheduled task?
|
+-- YES --> Cron job (vercel.json crons + api route)
|
+-- NO --> Is it an API endpoint?
|
+-- YES --> Vercel Function (api/ directory)
|
+-- NO --> Is it a static routing rule?
|
+-- YES --> vercel.json (headers/redirects/rewrites)
+-- NO --> Framework-specific solution
Is your configuration static and predictable?
|
+-- YES --> vercel.json
|
+-- NO --> Do you need env vars, API calls, or conditional logic at build time?
|
+-- YES --> vercel.ts (with @vercel/config)
+-- NO --> vercel.json
</decision_framework>
<red_flags>
High Priority Issues:
vercel.json or committing .env files -- use the Vercel dashboard Environment Variables or vercel env CLICRON_SECRET verification in cron handlers -- cron endpoints are publicly accessible URLs anyone can callmaxDuration above your plan limit -- deployment will failregions when your database is outside iad1 -- every function call makes a cross-region database round tripMedium Priority Issues:
$schema in vercel.json -- loses IDE autocompletion and validation that catches config errors before deploymentpermanent: true redirects during development -- browsers cache 308s aggressively, hard to undoignoreCommand in monorepos -- every commit triggers builds for all apps, wasting build minutesVERCEL_URL without protocol -- VERCEL_URL does not include https://, must be prependedCommon Mistakes:
statusCode and permanent together in redirects -- they are mutually exclusivefs modulebuilds property in vercel.json -- it is legacy, use functions insteadGotchas & Edge Cases:
eval(), new Function(), and dynamic WebAssembly.instantiate are disabled for securitycleanUrls: true causes 404s in local vercel dev but works in productionhas/missing conditions on redirects/headers don't work locally with vercel devVERCEL_URL differs between Production (custom domain) and Preview (generated .vercel.app URL)memory cannot be set in vercel.json when Fluid compute is enabled -- use the dashboard insteadvercel.ts only runs at build time, not at request time -- it generates static config</red_flags>
<critical_reminders>
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST always include "$schema": "https://openapi.vercel.sh/vercel.json" in vercel.json for IDE validation)
(You MUST place functions in a region close to your data source -- the default iad1 may add latency if your database is elsewhere)
(You MUST verify CRON_SECRET in cron job handlers -- Vercel cron endpoints are publicly accessible URLs)
(You MUST design cron jobs to be idempotent -- Vercel may deliver the same cron event more than once)
(You MUST NOT store secrets in vercel.json or source code -- use Environment Variables in the Vercel dashboard)
Failure to follow these rules will result in security vulnerabilities (exposed secrets, unprotected cron endpoints), poor performance (cross-region latency), and deployment failures (invalid config, exceeded limits).
</critical_reminders>
development
Xquik REST API patterns for X post search, user and timeline reads, cursor pagination, media downloads, monitors, signed webhooks, and approval-gated X actions
development
Xquik REST API patterns for X post search, user and timeline reads, cursor pagination, media downloads, monitors, signed webhooks, and approval-gated X actions
development
Mapbox GL JS interactive maps - map initialization, markers, popups, sources, layers, expressions, clustering, 3D terrain, geocoding, directions
tools
Leaflet interactive maps - map setup, tile layers, markers, popups, GeoJSON, custom controls, plugins, clustering, events