← VercelCONTENT HISTORY

Update to Vercel

Snapshot Oct 6, 2026 · 18:03 UTC · version 0.54.1

Collection source: downloaded plugin package. These snapshots do not have a confirmed matching collection source. Differences in file lists alone do not establish changes to the package.

WHAT CHANGED · RULE-BASED ANALYSIS

Payment or plan references changed

Instruction wording changed from “"https://nextjs.org/docs/app/building-your-application/routing/middleware"” to “"https://nextjs.org/docs/app/api-reference/file-conventions/proxy"”. 64 additional added or edited lines are in the evidence.

Observed in published text. Live prices and checkout terms have not been verified by this change.

Skill instructions

Before

"https://nextjs.org/docs/app/building-your-application/routing/middleware" - **File**: `middleware.ts` or `middleware.js` at the project root - **Default export required** (function name can be anything) - **Runtimes**: Edge (default), N...

After

"https://nextjs.org/docs/app/api-reference/file-conventions/proxy" validate: - pattern: 'NextResponse.*from\s+[''"]next/server[''"]|from\s+[''"]next/server[''"].*NextResponse' message: 'Next.js middleware.ts is renamed to proxy...

Compare saved observations

Download comparison JSON
Full technical diff · 1 changed fields

changed /skill_md_contents

BEFORE
"---\nname: routing-middleware\ndescription: Vercel Routing Middleware guidance — request interception before cache, rewrites, redirects, personalization. Works with any framework. Supports Edge, Node.js, and Bun runtimes. Use when intercepting requests at the platform level.\nmetadata:\n  priority: 6\n  docs:\n    - \"https://nextjs.org/docs/app/building-your-application/routing/middleware\"\n    - \"https://vercel.com/docs/routing-middleware\"\n  sitemap: \"https://nextjs.org/sitemap.xml\"\n  pathPatterns: \n    - 'middleware.ts'\n    - 'middleware.js'\n    - 'middleware.mts'\n    - 'middleware.mjs'\n    - 'proxy.ts'\n    - 'proxy.js'\n    - 'proxy.mts'\n    - 'proxy.mjs'\n    - 'src/middleware.ts'\n    - 'src/middleware.js'\n    - 'src/middleware.mts'\n    - 'src/middleware.mjs'\n    - 'src/proxy.ts'\n    - 'src/proxy.js'\n    - 'src/proxy.mts'\n    - 'src/proxy.mjs'\n    - 'vercel.json'\n    - 'apps/*/vercel.json'\n    - 'vercel.ts'\n    - 'vercel.mts'\n  bashPatterns:\n    - '\\bnpx\\s+@vercel/config\\b'\n---\n\n# Vercel Routing Middleware\n\nYou are an expert in Vercel Routing Middleware — the platform-level request interception layer.\n\n## What It Is\n\nRouting Middleware runs **before the cache** on every request matching its config. It is a **Vercel platform** feature (not framework-specific) that works with Next.js, SvelteKit, Astro, Nuxt, or any deployed framework. Built on Fluid Compute.\n\n- **File**: `middleware.ts` or `middleware.js` at the project root\n- **Default export required** (function name can be anything)\n- **Runtimes**: Edge (default), Node.js (`runtime: 'nodejs'`), Bun (Node.js + `bunVersion` in vercel.json)\n\n## CRITICAL: Middleware Disambiguation\n\nThere are THREE \"middleware\" concepts in the Vercel ecosystem:\n\n| Concept | File | Runtime | Scope | When to Use |\n|---------|------|---------|-------|-------------|\n| **Vercel Routing Middleware** | `middleware.ts` (root) | Edge/Node/Bun | Any framework, platform-level | Request interception before cache: rewrites, redirects, geo, A/B |\n| **Next.js 16 Proxy** | `proxy.ts` (root, or `src/proxy.ts` if using `--src-dir`) | Node.js only | Next.js 16+ only | Network-boundary proxy needing full Node APIs. NOT for auth. |\n| **Edge Functions** | Any function file | V8 isolates | General-purpose | Standalone edge compute endpoints, not an interception layer |\n\n**Why the rename in Next.js 16**: `middleware.ts` → `proxy.ts` clarifies it sits at the network boundary (not general-purpose middleware). Partly motivated by CVE-2025-29927 (middleware auth bypass via `x-middleware-subrequest` header). The exported function must also be renamed from `middleware` to `proxy`. Migration codemod: `npx @next/codemod@latest middleware-to-proxy`\n\n**Deprecation**: Next.js 16 still accepts `middleware.ts` but treats it as deprecated and logs a warning. It will be removed in a future version.\n\n## Bun Runtime\n\nTo run Routing Middleware (and all Vercel Functions) on Bun, add `bunVersion` to `vercel.json`:\n\n```json\n{\n  \"bunVersion\": \"1.x\"\n}\n```\n\nSet the middleware runtime to `nodejs` — Bun replaces the Node.js runtime transparently:\n\n```ts\nexport const config = {\n  runtime: 'nodejs', // Bun swaps in when bunVersion is set\n};\n```\n\nBun reduces average latency by ~28% in CPU-bound workloads. Currently in Public Beta — supports Next.js, Express, Hono, and Nitro.\n\n## Basic Example\n\n```ts\n// middleware.ts (project root)\nimport { geolocation, rewrite } from '@vercel/functions';\n\nexport default function middleware(request: Request) {\n  const { country } = geolocation(request);\n  const url = new URL(request.url);\n  url.pathname = country === 'US' ? '/us' + url.pathname : '/intl' + url.pathname;\n  return rewrite(url);\n}\n\nexport const config = {\n  runtime: 'edge', // 'edge' (default) | 'nodejs'\n};\n```\n\n## Helper Methods (`@vercel/functions`)\n\nFor non-Next.js frameworks, import from `@vercel/functions`:\n\n| Helper | Purpose |\n|--------|---------|\n| `next()` | Continue middleware chain (optionally modify headers) |\n| `rewrite(url)` | Transparently serve content from a different URL |\n| `geolocation(request)` | Get `city`, `country`, `latitude`, `longitude`, `region` |\n| `ipAddress(request)` | Get client IP address |\n| `waitUntil(promise)` | Keep function running after response is sent |\n\nFor Next.js, equivalent helpers are on `NextResponse` (`next()`, `rewrite()`, `redirect()`) and `NextRequest` (`request.geo`, `request.ip`).\n\n## Matcher Configuration\n\nMiddleware runs on **every route** by default. Use `config.matcher` to scope it:\n\n```ts\n// Single path\nexport const config = { matcher: '/dashboard/:path*' };\n\n// Multiple paths\nexport const config = { matcher: ['/dashboard/:path*', '/api/:path*'] };\n\n// Regex: exclude static files\nexport const config = {\n  matcher: ['/((?!_next/static|favicon.ico).*)'],\n};\n```\n\n**Tip**: Using `matcher` is preferred — unmatched paths skip middleware invocation entirely (saves compute).\n\n## Common Patterns\n\n### IP-Based Header Injection\n\n```ts\nimport { ipAddress, next } from '@vercel/functions';\n\nexport default function middleware(request: Request) {\n  return next({ headers: { 'x-real-ip': ipAddress(request) || 'unknown' } });\n}\n```\n\n### A/B Testing via Edge Config\n\n```ts\nimport { get } from '@vercel/edge-config';\nimport { rewrite } from '@vercel/functions';\n\nexport default async function middleware(request: Request) {\n  const variant = await get('experiment-homepage'); // <1ms read\n  const url = new URL(request.url);\n  url.pathname = variant === 'B' ? '/home-b' : '/home-a';\n  return rewrite(url);\n}\n```\n\n### Background Processing\n\n```ts\nimport type { RequestContext } from '@vercel/functions';\n\nexport default function middleware(request: Request, context: RequestContext) {\n  context.waitUntil(\n    fetch('https://analytics.example.com/log', { method: 'POST', body: request.url })\n  );\n  return new Response('OK');\n}\n```\n\n## Request Limits\n\n| Limit | Value |\n|-------|-------|\n| Max URL length | 14 KB |\n| Max request body | 4 MB |\n| Max request headers | 64 headers / 16 KB total |\n\n## Three CDN Routing Mechanisms\n\nVercel's CDN supports three routing mechanisms, evaluated in this order:\n\n| Order | Mechanism | Scope | Deploy Required | How to Configure |\n|-------|-----------|-------|-----------------|------------------|\n| 1 | **Bulk Redirects** | Up to 1M static path→path redirects | No (runtime via Dashboard/API/CLI) | Dashboard, CSV upload, REST API |\n| 2 | **Project-Level Routes** | Headers, rewrites, redirects | No (instant publish) | Dashboard, API, CLI, Vercel SDK |\n| 3 | **Deployment Config Routes** | Full routing rules | Yes (deploy) | `vercel.json`, `vercel.ts`, `next.config.ts` |\n\n**Project-level routes** (added March 2026) let you update routing rules — response headers, rewrites to external APIs — without triggering a new deployment. They run after bulk redirects and before deployment config routes. Available on all plans.\n\n### Project-Level Routes — Configuration Methods\n\nProject-level routes take effect instantly (no deploy required). Four ways to manage them:\n\n| Method | How |\n|--------|-----|\n| **Dashboard** | Project → CDN → Routing tab. Live map of global traffic, cache management, and route editor in one view. |\n| **REST API** | `GET/POST/PATCH/DELETE /v1/projects/{projectId}/routes` — 8 dedicated endpoints for CRUD on project routes. |\n| **Vercel CLI** | Managed via `vercel.ts` / `@vercel/config` commands (`compile`, `validate`, `generate`). |\n| **Vercel SDK** | `@vercel/config` helpers: `routes.redirect()`, `routes.rewrite()`, `routes.header()`, plus `has`/`missing` conditions and transforms. |\n\nUse project-level routes for operational changes (CORS headers, API proxy rewrites, A/B redirects) that shouldn't require a full redeploy.\n\n## Programmatic Configuration with `vercel.ts`\n\nInstead of static `vercel.json`, you can use `vercel.ts` (or `.js`, `.mjs`, `.cjs`, `.mts`) with the `@vercel/config` package for type-safe, dynamic routing configuration:\n\n```ts\n// vercel.ts\nimport { defineConfig } from '@vercel/config';\n\nexport default defineConfig({\n  rewrites: [\n    { source: '/api/:path*', destination: 'https://backend.example.com/:path*' },\n  ],\n  headers: [\n    { source: '/(.*)', headers: [{ key: 'X-Frame-Options', value: 'DENY' }] },\n  ],\n});\n```\n\nCLI commands:\n- `npx @vercel/config compile` — compile to JSON (stdout)\n- `npx @vercel/config validate` — validate and show summary\n- `npx @vercel/config generate` — generate `vercel.json` locally for development\n\n**Constraint**: Only one config file per project — `vercel.json` or `vercel.ts`, not both.\n\n## When to Use\n\n- Geo-personalization of static pages (runs before cache)\n- A/B testing rewrites with Edge Config\n- Custom redirects based on request properties\n- Header injection (CSP, CORS, custom headers)\n- Lightweight auth checks (defense-in-depth only — not sole auth layer)\n- Project-level routes for headers/rewrites without redeploying\n\n## When NOT to Use\n\n- Need full Node.js APIs in Next.js → use `proxy.ts`\n- General compute at the edge → use Edge Functions\n- Heavy business logic or database queries → use server-side framework features\n- Auth as sole protection → use Layouts, Server Components, or Route Handlers\n- Thousands of static redirects → use Bulk Redirects (up to 1M per project)\n\n## References\n\n- 📖 docs: https://vercel.com/docs/routing-middleware\n- 📖 API reference: https://vercel.com/docs/routing-middleware/api\n- 📖 getting started: https://vercel.com/docs/routing-middleware/getting-started\n"
AFTER
"---\nname: routing-middleware\ndescription: Vercel Routing Middleware guidance — request interception before cache, rewrites, redirects, personalization. Works with any framework. Supports Edge, Node.js, and Bun runtimes. Use when intercepting requests at the platform level.\nmetadata:\n  priority: 6\n  docs:\n    - \"https://nextjs.org/docs/app/api-reference/file-conventions/proxy\"\n    - \"https://vercel.com/docs/routing-middleware\"\n  sitemap: \"https://nextjs.org/sitemap.xml\"\n  pathPatterns: \n    - 'middleware.ts'\n    - 'middleware.js'\n    - 'middleware.mts'\n    - 'middleware.mjs'\n    - 'proxy.ts'\n    - 'proxy.js'\n    - 'proxy.mts'\n    - 'proxy.mjs'\n    - 'src/middleware.ts'\n    - 'src/middleware.js'\n    - 'src/middleware.mts'\n    - 'src/middleware.mjs'\n    - 'src/proxy.ts'\n    - 'src/proxy.js'\n    - 'src/proxy.mts'\n    - 'src/proxy.mjs'\n    - 'vercel.json'\n    - 'apps/*/vercel.json'\n    - 'vercel.ts'\n    - 'vercel.mts'\n  bashPatterns:\n    - '\\bnpx\\s+@vercel/config\\b'\nvalidate:\n  -\n    pattern: 'NextResponse.*from\\s+[''\"]next/server[''\"]|from\\s+[''\"]next/server[''\"].*NextResponse'\n    message: 'Next.js middleware.ts is renamed to proxy.ts in Next.js 16 — rename the file and use the Node.js runtime. See the proxy file convention in the bundled docs at node_modules/next/dist/docs/.'\n    severity: recommended\n    skipIfFileContains: 'proxy\\.ts|runtime.*nodejs'\nretrieval:\n  aliases:\n    - request interceptor\n    - middleware\n    - rewrite rules\n    - redirect rules\n  intents:\n    - intercept requests\n    - add middleware\n    - configure rewrites\n    - set up redirects\n  entities:\n    - middleware\n    - rewrite\n    - redirect\n    - personalization\n    - Edge\nchainTo:\n  -\n    pattern: 'from\\s+[''\"\"]next-auth[''\"\"]'\n    targetSkill: auth\n    message: 'Auth logic in middleware — loading Auth guidance for Clerk/Auth0 integration patterns.'\n  -\n    pattern: 'from\\s+[''\"\"](jsonwebtoken)[''\"\"]|jwt\\.(verify|decode)\\('\n    targetSkill: auth\n    message: 'Manual JWT verification in middleware — loading Auth guidance for managed auth middleware patterns (Clerk, Descope).'\n    skipIfFileContains: 'clerkMiddleware|@clerk/|@auth0/'\n\n---\n\n# Vercel Routing Middleware\n\nYou are an expert in Vercel Routing Middleware — the platform-level request interception layer.\n\n## What It Is\n\nRouting Middleware runs **before the cache** on every request matching its config. It is a **Vercel platform** feature (not framework-specific) that works with Next.js, SvelteKit, Astro, Nuxt, or any deployed framework. Built on Fluid Compute.\n\n- **Preferred platform configuration**: Set `proxy.entrypoint` in `vercel.json`. The entrypoint can use any supported filename or directory and runs on Node.js. Frameworks that build their own routing middleware (Next.js, Astro) do not use the `proxy` property; use the framework's file convention instead.\n- **File convention**: `middleware.ts` or `middleware.js` at the project root. This convention defaults to Edge; set `runtime: 'nodejs'` to use Node.js.\n- **Next.js 16**: Use `proxy.ts` and export `proxy`. Next.js Proxy runs on Node.js only.\n\n## CRITICAL: Middleware Disambiguation\n\nThere are THREE \"middleware\" concepts in the Vercel ecosystem:\n\n| Concept | File | Runtime | Scope | When to Use |\n|---------|------|---------|-------|-------------|\n| **Vercel Routing Middleware** | `proxy.entrypoint` or `middleware.ts` | Node/Edge/Bun | Any framework, platform-level | Request interception before cache: rewrites, redirects, geo, A/B |\n| **Next.js 16 Proxy** | `proxy.ts` (root, or `src/proxy.ts` if using `--src-dir`) | Node.js only | Next.js 16+ only | Network-boundary proxy needing full Node APIs. NOT for auth. |\n| **Vercel Functions** | Route or function file | Node/Bun/Python/Rust | General-purpose | Request handlers and backend compute, not an interception layer |\n\n**Why the rename in Next.js 16** (`middleware.ts` → `proxy.ts`): \"middleware\" was often confused with Express.js middleware, and Next.js recommends the feature only as a last resort while it builds better APIs; \"proxy\" says what it is, a network boundary in front of the app. The exported function must also be renamed from `middleware` to `proxy`. Migration codemod: `npx @next/codemod@latest middleware-to-proxy .`\n\n**Deprecation**: Next.js 16 still accepts `middleware.ts` but treats it as deprecated and logs a warning. It will be removed in a future version.\n\n## Bun Runtime\n\nTo run Routing Middleware (and all Vercel Functions) on Bun, add `bunVersion` to `vercel.json`:\n\n```json filename=\"vercel.json\"\n{\n  \"bunVersion\": \"1.x\"\n}\n```\n\nSet the middleware runtime to `nodejs` — Bun replaces the Node.js runtime transparently:\n\n```ts\nexport const config = {\n  runtime: 'nodejs', // Bun swaps in when bunVersion is set\n};\n```\n\nBun reduces average latency by ~28% in CPU-bound workloads. Currently in Public Beta — supports Next.js, Express, Hono, and Nitro.\n\n## Basic Example\n\nConfigure an explicit entrypoint for framework-agnostic Routing Middleware:\n\n```json\n{\n  \"$schema\": \"https://openapi.vercel.sh/vercel.json\",\n  \"proxy\": {\n    \"entrypoint\": \"proxy.ts\",\n    \"matcher\": [\"/((?!_next/static|favicon.ico).*)\"]\n  }\n}\n```\n\n```ts\n// proxy.ts\nimport { geolocation, rewrite } from '@vercel/functions';\n\nexport default function proxy(request: Request) {\n  const { country } = geolocation(request);\n  const url = new URL(request.url);\n  url.pathname = country === 'US' ? '/us' + url.pathname : '/intl' + url.pathname;\n  return rewrite(url);\n}\n```\n\n## Helper Methods (`@vercel/functions`)\n\nFor non-Next.js frameworks, import from `@vercel/functions`:\n\n| Helper | Purpose |\n|--------|---------|\n| `next()` | Continue middleware chain (optionally modify headers) |\n| `rewrite(url)` | Transparently serve content from a different URL |\n| `geolocation(request)` | Get `city`, `country`, `latitude`, `longitude`, `region` |\n| `ipAddress(request)` | Get client IP address |\n| `waitUntil(promise)` | Keep function running after response is sent |\n\nFor Next.js, `NextResponse` provides `next()`, `rewrite()`, and `redirect()`. Use `geolocation(request)` and `ipAddress(request)` from `@vercel/functions`; `NextRequest.geo` and `NextRequest.ip` were removed in Next.js 15.\n\n## Matcher Configuration\n\nMiddleware runs on **every route** by default. Use `config.matcher` to scope it:\n\n```ts\n// Single path\nexport const config = { matcher: '/dashboard/:path*' };\n\n// Multiple paths\nexport const config = { matcher: ['/dashboard/:path*', '/api/:path*'] };\n\n// Regex: exclude static files\nexport const config = {\n  matcher: ['/((?!_next/static|favicon.ico).*)'],\n};\n```\n\n**Tip**: Using `matcher` is preferred — unmatched paths skip middleware invocation entirely (saves compute).\n\n## Common Patterns\n\n### IP-Based Header Injection\n\n```ts\nimport { ipAddress, next } from '@vercel/functions';\n\nexport default function middleware(request: Request) {\n  return next({ headers: { 'x-real-ip': ipAddress(request) || 'unknown' } });\n}\n```\n\n### A/B Testing via Global Config\n\n```ts\nimport { get } from '@vercel/global-config';\nimport { rewrite } from '@vercel/functions';\n\nexport default async function middleware(request: Request) {\n  const variant = await get('experiment-homepage'); // <1ms read\n  const url = new URL(request.url);\n  url.pathname = variant === 'B' ? '/home-b' : '/home-a';\n  return rewrite(url);\n}\n```\n\n### Background Processing\n\n```ts\nimport { waitUntil } from '@vercel/functions';\n\nexport default function middleware(request: Request) {\n  waitUntil(\n    fetch('https://analytics.example.com/log', { method: 'POST', body: request.url })\n  );\n  return new Response('OK');\n}\n```\n\n## Request Limits\n\n| Limit | Value |\n|-------|-------|\n| Max URL length | 14 KB |\n| Max request body | 4 MB |\n| Max request headers | 64 headers / 16 KB total |\n\n## Three CDN Routing Mechanisms\n\nVercel's CDN supports three routing mechanisms, evaluated in this order:\n\n| Order | Mechanism | Scope | Deploy Required | How to Configure |\n|-------|-----------|-------|-----------------|------------------|\n| 1 | **Bulk Redirects** | Up to 1M static path→path redirects | No (runtime via Dashboard/API/CLI) | Dashboard, CSV upload, REST API |\n| 2 | **Project-Level Routes** | Headers, rewrites, redirects | No (instant publish) | Dashboard, REST API, `vercel routes` CLI |\n| 3 | **Deployment Config Routes** | Full routing rules | Yes (deploy) | `vercel.json`, `vercel.ts`, `next.config.ts` |\n\n**Project-level routes** (added March 2026) let you update routing rules — response headers, rewrites to external APIs — without triggering a new deployment. They run after bulk redirects and before deployment config routes. Available on all plans.\n\n### Project-Level Routes — Configuration Methods\n\nProject-level routes take effect instantly (no deploy required). Three ways to manage them:\n\n| Method | How |\n|--------|-----|\n| **Dashboard** | Project → CDN → Routing tab. Live map of global traffic, cache management, and route editor in one view. |\n| **REST API** | `GET/POST/PATCH/DELETE /v1/projects/{projectId}/routes` — 8 dedicated endpoints for CRUD on project routes. |\n| **Vercel CLI** | Use `vercel routes` to stage, inspect, publish, restore, and export project-level rules. |\n\nDeployment-level routes in `vercel.json`, `vercel.ts`, or framework config are a separate mechanism (row 3 above) and require a deploy.\n\nUse project-level routes for operational changes (CORS headers, API proxy rewrites, A/B redirects) that shouldn't require a full redeploy.\n\n## Programmatic Configuration with `vercel.ts`\n\nInstead of static `vercel.json`, you can use `vercel.ts` (or `.js`, `.mjs`, `.cjs`, `.mts`) with the `@vercel/config` package for type-safe, dynamic routing configuration:\n\n```ts\n// vercel.ts\nimport { routes, type VercelConfig } from '@vercel/config/v1';\n\nexport const config: VercelConfig = {\n  rewrites: [\n    routes.rewrite('/api/(.*)', 'https://backend.example.com/$1'),\n  ],\n  headers: [\n    routes.header('/(.*)', [{ key: 'X-Frame-Options', value: 'DENY' }]),\n  ],\n};\n```\n\nFor project-level rules that take effect without a deployment, use `vercel routes add`, inspect staged changes with `vercel routes list --diff`, then run `vercel routes publish`.\n\n**Constraint**: Only one config file per project — `vercel.json` or `vercel.ts`, not both.\n\n## When to Use\n\n- Geo-personalization of static pages (runs before cache)\n- A/B testing rewrites with Global Config\n- Custom redirects based on request properties\n- Header injection (CSP, CORS, custom headers)\n- Lightweight auth checks (defense-in-depth only — not sole auth layer)\n- Project-level routes for headers/rewrites without redeploying\n\n## When NOT to Use\n\n- Need full Node.js APIs in Next.js → use `proxy.ts`\n- General compute or request handling → use Vercel Functions on the default Node.js runtime\n- Heavy business logic or database queries → use server-side framework features\n- Auth as sole protection → use Layouts, Server Components, or Route Handlers\n- Thousands of static redirects → use Bulk Redirects (up to 1M per project)\n\n## References\n\n- 📖 docs: https://vercel.com/docs/routing-middleware\n- 📖 API reference: https://vercel.com/docs/routing-middleware/api\n- 📖 getting started: https://vercel.com/docs/routing-middleware/getting-started\n"

SKILL.md line diff

--- before
+++ after
@@ -4,7 +4,7 @@
 metadata:
   priority: 6
   docs:
-    - "https://nextjs.org/docs/app/building-your-application/routing/middleware"
+    - "https://nextjs.org/docs/app/api-reference/file-conventions/proxy"
     - "https://vercel.com/docs/routing-middleware"
   sitemap: "https://nextjs.org/sitemap.xml"
   pathPatterns: 
@@ -30,6 +30,40 @@
     - 'vercel.mts'
   bashPatterns:
     - '\bnpx\s+@vercel/config\b'
+validate:
+  -
+    pattern: 'NextResponse.*from\s+[''"]next/server[''"]|from\s+[''"]next/server[''"].*NextResponse'
+    message: 'Next.js middleware.ts is renamed to proxy.ts in Next.js 16 — rename the file and use the Node.js runtime. See the proxy file convention in the bundled docs at node_modules/next/dist/docs/.'
+    severity: recommended
+    skipIfFileContains: 'proxy\.ts|runtime.*nodejs'
+retrieval:
+  aliases:
+    - request interceptor
+    - middleware
+    - rewrite rules
+    - redirect rules
+  intents:
+    - intercept requests
+    - add middleware
+    - configure rewrites
+    - set up redirects
+  entities:
+    - middleware
+    - rewrite
+    - redirect
+    - personalization
+    - Edge
+chainTo:
+  -
+    pattern: 'from\s+[''""]next-auth[''""]'
+    targetSkill: auth
+    message: 'Auth logic in middleware — loading Auth guidance for Clerk/Auth0 integration patterns.'
+  -
+    pattern: 'from\s+[''""](jsonwebtoken)[''""]|jwt\.(verify|decode)\('
+    targetSkill: auth
+    message: 'Manual JWT verification in middleware — loading Auth guidance for managed auth middleware patterns (Clerk, Descope).'
+    skipIfFileContains: 'clerkMiddleware|@clerk/|@auth0/'
+
 ---
 
 # Vercel Routing Middleware
@@ -40,9 +74,9 @@
 
 Routing Middleware runs **before the cache** on every request matching its config. It is a **Vercel platform** feature (not framework-specific) that works with Next.js, SvelteKit, Astro, Nuxt, or any deployed framework. Built on Fluid Compute.
 
-- **File**: `middleware.ts` or `middleware.js` at the project root
-- **Default export required** (function name can be anything)
-- **Runtimes**: Edge (default), Node.js (`runtime: 'nodejs'`), Bun (Node.js + `bunVersion` in vercel.json)
+- **Preferred platform configuration**: Set `proxy.entrypoint` in `vercel.json`. The entrypoint can use any supported filename or directory and runs on Node.js. Frameworks that build their own routing middleware (Next.js, Astro) do not use the `proxy` property; use the framework's file convention instead.
+- **File convention**: `middleware.ts` or `middleware.js` at the project root. This convention defaults to Edge; set `runtime: 'nodejs'` to use Node.js.
+- **Next.js 16**: Use `proxy.ts` and export `proxy`. Next.js Proxy runs on Node.js only.
 
 ## CRITICAL: Middleware Disambiguation
 
@@ -50,11 +84,11 @@
 
 | Concept | File | Runtime | Scope | When to Use |
 |---------|------|---------|-------|-------------|
-| **Vercel Routing Middleware** | `middleware.ts` (root) | Edge/Node/Bun | Any framework, platform-level | Request interception before cache: rewrites, redirects, geo, A/B |
+| **Vercel Routing Middleware** | `proxy.entrypoint` or `middleware.ts` | Node/Edge/Bun | Any framework, platform-level | Request interception before cache: rewrites, redirects, geo, A/B |
 | **Next.js 16 Proxy** | `proxy.ts` (root, or `src/proxy.ts` if using `--src-dir`) | Node.js only | Next.js 16+ only | Network-boundary proxy needing full Node APIs. NOT for auth. |
-| **Edge Functions** | Any function file | V8 isolates | General-purpose | Standalone edge compute endpoints, not an interception layer |
+| **Vercel Functions** | Route or function file | Node/Bun/Python/Rust | General-purpose | Request handlers and backend compute, not an interception layer |
 
-**Why the rename in Next.js 16**: `middleware.ts` → `proxy.ts` clarifies it sits at the network boundary (not general-purpose middleware). Partly motivated by CVE-2025-29927 (middleware auth bypass via `x-middleware-subrequest` header). The exported function must also be renamed from `middleware` to `proxy`. Migration codemod: `npx @next/codemod@latest middleware-to-proxy`
+**Why the rename in Next.js 16** (`middleware.ts` → `proxy.ts`): "middleware" was often confused with Express.js middleware, and Next.js recommends the feature only as a last resort while it builds better APIs; "proxy" says what it is, a network boundary in front of the app. The exported function must also be renamed from `middleware` to `proxy`. Migration codemod: `npx @next/codemod@latest middleware-to-proxy .`
 
 **Deprecation**: Next.js 16 still accepts `middleware.ts` but treats it as deprecated and logs a warning. It will be removed in a future version.
 
@@ -62,7 +96,7 @@
 
 To run Routing Middleware (and all Vercel Functions) on Bun, add `bunVersion` to `vercel.json`:
 
-```json
+```json filename="vercel.json"
 {
   "bunVersion": "1.x"
 }
@@ -80,20 +114,28 @@
 
 ## Basic Example
 
+Configure an explicit entrypoint for framework-agnostic Routing Middleware:
+
+```json
+{
+  "$schema": "https://openapi.vercel.sh/vercel.json",
+  "proxy": {
+    "entrypoint": "proxy.ts",
+    "matcher": ["/((?!_next/static|favicon.ico).*)"]
+  }
+}
+```
+
 ```ts
-// middleware.ts (project root)
+// proxy.ts
 import { geolocation, rewrite } from '@vercel/functions';
 
-export default function middleware(request: Request) {
+export default function proxy(request: Request) {
   const { country } = geolocation(request);
   const url = new URL(request.url);
   url.pathname = country === 'US' ? '/us' + url.pathname : '/intl' + url.pathname;
   return rewrite(url);
 }
-
-export const config = {
-  runtime: 'edge', // 'edge' (default) | 'nodejs'
-};
 ```
 
 ## Helper Methods (`@vercel/functions`)
@@ -108,7 +150,7 @@
 | `ipAddress(request)` | Get client IP address |
 | `waitUntil(promise)` | Keep function running after response is sent |
 
-For Next.js, equivalent helpers are on `NextResponse` (`next()`, `rewrite()`, `redirect()`) and `NextRequest` (`request.geo`, `request.ip`).
+For Next.js, `NextResponse` provides `next()`, `rewrite()`, and `redirect()`. Use `geolocation(request)` and `ipAddress(request)` from `@vercel/functions`; `NextRequest.geo` and `NextRequest.ip` were removed in Next.js 15.
 
 ## Matcher Configuration
 
@@ -141,10 +183,10 @@
 }
 ```
 
-### A/B Testing via Edge Config
+### A/B Testing via Global Config
 
 ```ts
-import { get } from '@vercel/edge-config';
+import { get } from '@vercel/global-config';
 import { rewrite } from '@vercel/functions';
 
 export default async function middleware(request: Request) {
@@ -158,10 +200,10 @@
 ### Background Processing
 
 ```ts
-import type { RequestContext } from '@vercel/functions';
+import { waitUntil } from '@vercel/functions';
 
-export default function middleware(request: Request, context: RequestContext) {
-  context.waitUntil(
+export default function middleware(request: Request) {
+  waitUntil(
     fetch('https://analytics.example.com/log', { method: 'POST', body: request.url })
   );
   return new Response('OK');
@@ -183,21 +225,22 @@
 | Order | Mechanism | Scope | Deploy Required | How to Configure |
 |-------|-----------|-------|-----------------|------------------|
 | 1 | **Bulk Redirects** | Up to 1M static path→path redirects | No (runtime via Dashboard/API/CLI) | Dashboard, CSV upload, REST API |
-| 2 | **Project-Level Routes** | Headers, rewrites, redirects | No (instant publish) | Dashboard, API, CLI, Vercel SDK |
+| 2 | **Project-Level Routes** | Headers, rewrites, redirects | No (instant publish) | Dashboard, REST API, `vercel routes` CLI |
 | 3 | **Deployment Config Routes** | Full routing rules | Yes (deploy) | `vercel.json`, `vercel.ts`, `next.config.ts` |
 
 **Project-level routes** (added March 2026) let you update routing rules — response headers, rewrites to external APIs — without triggering a new deployment. They run after bulk redirects and before deployment config routes. Available on all plans.
 
 ### Project-Level Routes — Configuration Methods
 
-Project-level routes take effect instantly (no deploy required). Four ways to manage them:
+Project-level routes take effect instantly (no deploy required). Three ways to manage them:
 
 | Method | How |
 |--------|-----|
 | **Dashboard** | Project → CDN → Routing tab. Live map of global traffic, cache management, and route editor in one view. |
 | **REST API** | `GET/POST/PATCH/DELETE /v1/projects/{projectId}/routes` — 8 dedicated endpoints for CRUD on project routes. |
-| **Vercel CLI** | Managed via `vercel.ts` / `@vercel/config` commands (`compile`, `validate`, `generate`). |
-| **Vercel SDK** | `@vercel/config` helpers: `routes.redirect()`, `routes.rewrite()`, `routes.header()`, plus `has`/`missing` conditions and transforms. |
+| **Vercel CLI** | Use `vercel routes` to stage, inspect, publish, restore, and export project-level rules. |
+
+Deployment-level routes in `vercel.json`, `vercel.ts`, or framework config are a separate mechanism (row 3 above) and require a deploy.
 
 Use project-level routes for operational changes (CORS headers, API proxy rewrites, A/B redirects) that shouldn't require a full redeploy.
 
@@ -207,29 +250,26 @@
 
 ```ts
 // vercel.ts
-import { defineConfig } from '@vercel/config';
+import { routes, type VercelConfig } from '@vercel/config/v1';
 
-export default defineConfig({
+export const config: VercelConfig = {
   rewrites: [
-    { source: '/api/:path*', destination: 'https://backend.example.com/:path*' },
+    routes.rewrite('/api/(.*)', 'https://backend.example.com/$1'),
   ],
   headers: [
-    { source: '/(.*)', headers: [{ key: 'X-Frame-Options', value: 'DENY' }] },
+    routes.header('/(.*)', [{ key: 'X-Frame-Options', value: 'DENY' }]),
   ],
-});
+};
 ```
 
-CLI commands:
-- `npx @vercel/config compile` — compile to JSON (stdout)
-- `npx @vercel/config validate` — validate and show summary
-- `npx @vercel/config generate` — generate `vercel.json` locally for development
+For project-level rules that take effect without a deployment, use `vercel routes add`, inspect staged changes with `vercel routes list --diff`, then run `vercel routes publish`.
 
 **Constraint**: Only one config file per project — `vercel.json` or `vercel.ts`, not both.
 
 ## When to Use
 
 - Geo-personalization of static pages (runs before cache)
-- A/B testing rewrites with Edge Config
+- A/B testing rewrites with Global Config
 - Custom redirects based on request properties
 - Header injection (CSP, CORS, custom headers)
 - Lightweight auth checks (defense-in-depth only — not sole auth layer)
@@ -238,7 +278,7 @@
 ## When NOT to Use
 
 - Need full Node.js APIs in Next.js → use `proxy.ts`
-- General compute at the edge → use Edge Functions
+- General compute or request handling → use Vercel Functions on the default Node.js runtime
 - Heavy business logic or database queries → use server-side framework features
 - Auth as sole protection → use Layouts, Server Components, or Route Handlers
 - Thousands of static redirects → use Bulk Redirects (up to 1M per project)
Full snapshot data
{
  "description": "Vercel Routing Middleware guidance — request interception before cache, rewrites, redirects, personalization. Works with any framework. Supports Edge, Node.js, and Bun runtimes. Use when intercepting requests at the platform level.",
  "included_files": [
    {
      "relative_path": "agents/openai.yaml",
      "size_in_bytes": 182
    }
  ],
  "name": "routing-middleware",
  "skill_md_contents": "---\nname: routing-middleware\ndescription: Vercel Routing Middleware guidance — request interception before cache, rewrites, redirects, personalization. Works with any framework. Supports Edge, Node.js, and Bun runtimes. Use when intercepting requests at the platform level.\nmetadata:\n  priority: 6\n  docs:\n    - \"https://nextjs.org/docs/app/api-reference/file-conventions/proxy\"\n    - \"https://vercel.com/docs/routing-middleware\"\n  sitemap: \"https://nextjs.org/sitemap.xml\"\n  pathPatterns: \n    - 'middleware.ts'\n    - 'middleware.js'\n    - 'middleware.mts'\n    - 'middleware.mjs'\n    - 'proxy.ts'\n    - 'proxy.js'\n    - 'proxy.mts'\n    - 'proxy.mjs'\n    - 'src/middleware.ts'\n    - 'src/middleware.js'\n    - 'src/middleware.mts'\n    - 'src/middleware.mjs'\n    - 'src/proxy.ts'\n    - 'src/proxy.js'\n    - 'src/proxy.mts'\n    - 'src/proxy.mjs'\n    - 'vercel.json'\n    - 'apps/*/vercel.json'\n    - 'vercel.ts'\n    - 'vercel.mts'\n  bashPatterns:\n    - '\\bnpx\\s+@vercel/config\\b'\nvalidate:\n  -\n    pattern: 'NextResponse.*from\\s+[''\"]next/server[''\"]|from\\s+[''\"]next/server[''\"].*NextResponse'\n    message: 'Next.js middleware.ts is renamed to proxy.ts in Next.js 16 — rename the file and use the Node.js runtime. See the proxy file convention in the bundled docs at node_modules/next/dist/docs/.'\n    severity: recommended\n    skipIfFileContains: 'proxy\\.ts|runtime.*nodejs'\nretrieval:\n  aliases:\n    - request interceptor\n    - middleware\n    - rewrite rules\n    - redirect rules\n  intents:\n    - intercept requests\n    - add middleware\n    - configure rewrites\n    - set up redirects\n  entities:\n    - middleware\n    - rewrite\n    - redirect\n    - personalization\n    - Edge\nchainTo:\n  -\n    pattern: 'from\\s+[''\"\"]next-auth[''\"\"]'\n    targetSkill: auth\n    message: 'Auth logic in middleware — loading Auth guidance for Clerk/Auth0 integration patterns.'\n  -\n    pattern: 'from\\s+[''\"\"](jsonwebtoken)[''\"\"]|jwt\\.(verify|decode)\\('\n    targetSkill: auth\n    message: 'Manual JWT verification in middleware — loading Auth guidance for managed auth middleware patterns (Clerk, Descope).'\n    skipIfFileContains: 'clerkMiddleware|@clerk/|@auth0/'\n\n---\n\n# Vercel Routing Middleware\n\nYou are an expert in Vercel Routing Middleware — the platform-level request interception layer.\n\n## What It Is\n\nRouting Middleware runs **before the cache** on every request matching its config. It is a **Vercel platform** feature (not framework-specific) that works with Next.js, SvelteKit, Astro, Nuxt, or any deployed framework. Built on Fluid Compute.\n\n- **Preferred platform configuration**: Set `proxy.entrypoint` in `vercel.json`. The entrypoint can use any supported filename or directory and runs on Node.js. Frameworks that build their own routing middleware (Next.js, Astro) do not use the `proxy` property; use the framework's file convention instead.\n- **File convention**: `middleware.ts` or `middleware.js` at the project root. This convention defaults to Edge; set `runtime: 'nodejs'` to use Node.js.\n- **Next.js 16**: Use `proxy.ts` and export `proxy`. Next.js Proxy runs on Node.js only.\n\n## CRITICAL: Middleware Disambiguation\n\nThere are THREE \"middleware\" concepts in the Vercel ecosystem:\n\n| Concept | File | Runtime | Scope | When to Use |\n|---------|------|---------|-------|-------------|\n| **Vercel Routing Middleware** | `proxy.entrypoint` or `middleware.ts` | Node/Edge/Bun | Any framework, platform-level | Request interception before cache: rewrites, redirects, geo, A/B |\n| **Next.js 16 Proxy** | `proxy.ts` (root, or `src/proxy.ts` if using `--src-dir`) | Node.js only | Next.js 16+ only | Network-boundary proxy needing full Node APIs. NOT for auth. |\n| **Vercel Functions** | Route or function file | Node/Bun/Python/Rust | General-purpose | Request handlers and backend compute, not an interception layer |\n\n**Why the rename in Next.js 16** (`middleware.ts` → `proxy.ts`): \"middleware\" was often confused with Express.js middleware, and Next.js recommends the feature only as a last resort while it builds better APIs; \"proxy\" says what it is, a network boundary in front of the app. The exported function must also be renamed from `middleware` to `proxy`. Migration codemod: `npx @next/codemod@latest middleware-to-proxy .`\n\n**Deprecation**: Next.js 16 still accepts `middleware.ts` but treats it as deprecated and logs a warning. It will be removed in a future version.\n\n## Bun Runtime\n\nTo run Routing Middleware (and all Vercel Functions) on Bun, add `bunVersion` to `vercel.json`:\n\n```json filename=\"vercel.json\"\n{\n  \"bunVersion\": \"1.x\"\n}\n```\n\nSet the middleware runtime to `nodejs` — Bun replaces the Node.js runtime transparently:\n\n```ts\nexport const config = {\n  runtime: 'nodejs', // Bun swaps in when bunVersion is set\n};\n```\n\nBun reduces average latency by ~28% in CPU-bound workloads. Currently in Public Beta — supports Next.js, Express, Hono, and Nitro.\n\n## Basic Example\n\nConfigure an explicit entrypoint for framework-agnostic Routing Middleware:\n\n```json\n{\n  \"$schema\": \"https://openapi.vercel.sh/vercel.json\",\n  \"proxy\": {\n    \"entrypoint\": \"proxy.ts\",\n    \"matcher\": [\"/((?!_next/static|favicon.ico).*)\"]\n  }\n}\n```\n\n```ts\n// proxy.ts\nimport { geolocation, rewrite } from '@vercel/functions';\n\nexport default function proxy(request: Request) {\n  const { country } = geolocation(request);\n  const url = new URL(request.url);\n  url.pathname = country === 'US' ? '/us' + url.pathname : '/intl' + url.pathname;\n  return rewrite(url);\n}\n```\n\n## Helper Methods (`@vercel/functions`)\n\nFor non-Next.js frameworks, import from `@vercel/functions`:\n\n| Helper | Purpose |\n|--------|---------|\n| `next()` | Continue middleware chain (optionally modify headers) |\n| `rewrite(url)` | Transparently serve content from a different URL |\n| `geolocation(request)` | Get `city`, `country`, `latitude`, `longitude`, `region` |\n| `ipAddress(request)` | Get client IP address |\n| `waitUntil(promise)` | Keep function running after response is sent |\n\nFor Next.js, `NextResponse` provides `next()`, `rewrite()`, and `redirect()`. Use `geolocation(request)` and `ipAddress(request)` from `@vercel/functions`; `NextRequest.geo` and `NextRequest.ip` were removed in Next.js 15.\n\n## Matcher Configuration\n\nMiddleware runs on **every route** by default. Use `config.matcher` to scope it:\n\n```ts\n// Single path\nexport const config = { matcher: '/dashboard/:path*' };\n\n// Multiple paths\nexport const config = { matcher: ['/dashboard/:path*', '/api/:path*'] };\n\n// Regex: exclude static files\nexport const config = {\n  matcher: ['/((?!_next/static|favicon.ico).*)'],\n};\n```\n\n**Tip**: Using `matcher` is preferred — unmatched paths skip middleware invocation entirely (saves compute).\n\n## Common Patterns\n\n### IP-Based Header Injection\n\n```ts\nimport { ipAddress, next } from '@vercel/functions';\n\nexport default function middleware(request: Request) {\n  return next({ headers: { 'x-real-ip': ipAddress(request) || 'unknown' } });\n}\n```\n\n### A/B Testing via Global Config\n\n```ts\nimport { get } from '@vercel/global-config';\nimport { rewrite } from '@vercel/functions';\n\nexport default async function middleware(request: Request) {\n  const variant = await get('experiment-homepage'); // <1ms read\n  const url = new URL(request.url);\n  url.pathname = variant === 'B' ? '/home-b' : '/home-a';\n  return rewrite(url);\n}\n```\n\n### Background Processing\n\n```ts\nimport { waitUntil } from '@vercel/functions';\n\nexport default function middleware(request: Request) {\n  waitUntil(\n    fetch('https://analytics.example.com/log', { method: 'POST', body: request.url })\n  );\n  return new Response('OK');\n}\n```\n\n## Request Limits\n\n| Limit | Value |\n|-------|-------|\n| Max URL length | 14 KB |\n| Max request body | 4 MB |\n| Max request headers | 64 headers / 16 KB total |\n\n## Three CDN Routing Mechanisms\n\nVercel's CDN supports three routing mechanisms, evaluated in this order:\n\n| Order | Mechanism | Scope | Deploy Required | How to Configure |\n|-------|-----------|-------|-----------------|------------------|\n| 1 | **Bulk Redirects** | Up to 1M static path→path redirects | No (runtime via Dashboard/API/CLI) | Dashboard, CSV upload, REST API |\n| 2 | **Project-Level Routes** | Headers, rewrites, redirects | No (instant publish) | Dashboard, REST API, `vercel routes` CLI |\n| 3 | **Deployment Config Routes** | Full routing rules | Yes (deploy) | `vercel.json`, `vercel.ts`, `next.config.ts` |\n\n**Project-level routes** (added March 2026) let you update routing rules — response headers, rewrites to external APIs — without triggering a new deployment. They run after bulk redirects and before deployment config routes. Available on all plans.\n\n### Project-Level Routes — Configuration Methods\n\nProject-level routes take effect instantly (no deploy required). Three ways to manage them:\n\n| Method | How |\n|--------|-----|\n| **Dashboard** | Project → CDN → Routing tab. Live map of global traffic, cache management, and route editor in one view. |\n| **REST API** | `GET/POST/PATCH/DELETE /v1/projects/{projectId}/routes` — 8 dedicated endpoints for CRUD on project routes. |\n| **Vercel CLI** | Use `vercel routes` to stage, inspect, publish, restore, and export project-level rules. |\n\nDeployment-level routes in `vercel.json`, `vercel.ts`, or framework config are a separate mechanism (row 3 above) and require a deploy.\n\nUse project-level routes for operational changes (CORS headers, API proxy rewrites, A/B redirects) that shouldn't require a full redeploy.\n\n## Programmatic Configuration with `vercel.ts`\n\nInstead of static `vercel.json`, you can use `vercel.ts` (or `.js`, `.mjs`, `.cjs`, `.mts`) with the `@vercel/config` package for type-safe, dynamic routing configuration:\n\n```ts\n// vercel.ts\nimport { routes, type VercelConfig } from '@vercel/config/v1';\n\nexport const config: VercelConfig = {\n  rewrites: [\n    routes.rewrite('/api/(.*)', 'https://backend.example.com/$1'),\n  ],\n  headers: [\n    routes.header('/(.*)', [{ key: 'X-Frame-Options', value: 'DENY' }]),\n  ],\n};\n```\n\nFor project-level rules that take effect without a deployment, use `vercel routes add`, inspect staged changes with `vercel routes list --diff`, then run `vercel routes publish`.\n\n**Constraint**: Only one config file per project — `vercel.json` or `vercel.ts`, not both.\n\n## When to Use\n\n- Geo-personalization of static pages (runs before cache)\n- A/B testing rewrites with Global Config\n- Custom redirects based on request properties\n- Header injection (CSP, CORS, custom headers)\n- Lightweight auth checks (defense-in-depth only — not sole auth layer)\n- Project-level routes for headers/rewrites without redeploying\n\n## When NOT to Use\n\n- Need full Node.js APIs in Next.js → use `proxy.ts`\n- General compute or request handling → use Vercel Functions on the default Node.js runtime\n- Heavy business logic or database queries → use server-side framework features\n- Auth as sole protection → use Layouts, Server Components, or Route Handlers\n- Thousands of static redirects → use Bulk Redirects (up to 1M per project)\n\n## References\n\n- 📖 docs: https://vercel.com/docs/routing-middleware\n- 📖 API reference: https://vercel.com/docs/routing-middleware/api\n- 📖 getting started: https://vercel.com/docs/routing-middleware/getting-started\n"
}

SHA-256 of public snapshot: 7d238d4fbe5e7d5f7ec36c961aaa1d1803ad653301451e9af684a666f5062cd1