netlify/context-and-tools/netlify-edge-functions
Claude Code and agent skill by netlify/context-and-tools
- community
Checking that the SKILL.md file is still in the repository.
Write, route, cache, and debug Netlify Edge Functions, the Deno-based TypeScript or JavaScript handlers in netlify/edge-functions that run at the network edge in front of static files and serverless functions. Activate this skill whenever someone wants to add auth middleware or a login gate, redirect or rewrite visitors by country or cookie, localize or personalize a page with geolocation, run A/B testing, transform or inject HTML into a response, stream server-side rendering at the edge, or ca…
Install
npx vskill@latest install netlify/context-and-tools/netlify-edge-functionsSKILL.md
Netlify Edge Functions
Use this form
- One file = one function: a default-export handler plus a named
configexport with the route. Alternatively, declare the route innetlify.toml. - The default export can also be a Fetchable module: an object with a
fetchmethod. Netlify callsfetchwith the same(request, context)arguments and uses its return value the same way; insidefetch,thisis the exported object. Use it to share one handler with other platforms that accept Fetchable modules.
``ts export default { async fetch(request: Request, context: Context) { return new Response("Hello"); }, }; export const config: Config = { path: "/hello" }; // still a named export ``
RequestandResponseare global. ImportContextandConfigtypes from@netlify/edge-functions.- Read env vars with
Netlify.env.get().process.envworks only for Next.js middleware.
Avoid these:
- A file with no
config.pathorpatternand no[[edge_functions]]entry. It deploys but never runs. - Import maps in
deno.json. They are unsupported. Use a separate file with[functions] deno_import_map. - Variables set in
netlify.toml. They are invisible to edge functions. Netlify.env.set()orNetlify.env.delete()as persistence. They affect only the current invocation.fetch()to the same site for the current path. Usecontext.next()instead.
⚠️ Footguns
- No route = silent no-op. Edge functions get no automatic URL.
- `path: "/*"` runs on every request, including assets. Narrow it, or add
excludedPath. - Caching needs both parts:
cache: "manual"in config AND cache headers on the returnedResponse. With only one, nothing is cached. - Cached functions shadow static files. A cached function on
/*serves/cat.pnginstead of the file. - Returning a `Response` ends the chain. Redirect rules for that path never run.
- Same-site `fetch()` and `URL` rewrites start a new request chain. Matching edge functions run again. Use
context.next()to reach the static asset or serverless function at the same path. - The request body can be read once. After
await req.json(), passnew Request(req, { body })tocontext.next(). - Same-named `foo.ts` and `foo.js`: the TS file is ignored and the JS file deploys.
- 50 ms CPU per request, including
waitUntilwork. - Not executed on sites with Split Testing enabled.
- Custom Headers and basic-auth headers do not apply to edge functions.
- Not supported on HIPAA-compliant hosting.
- `netlify.app` is on the Public Suffix List. Cross-subdomain cookies need a custom domain.
Files
| What | Where | |
|---|---|---|
| Functions | <base>/netlify/edge-functions/*.{js,ts,jsx,tsx} | |
| Custom dir | [build] edge_functions = "my-dir" (relative to base dir; keep it outside the publish dir) | |
| Name in toml | file name without extension (auth.ts → function = "auth") | |
| Import map | any JSON file, referenced by [functions] deno_import_map = "./import_map.json" |
Return values
| Return | Effect | |
|---|---|---|
Response | sent to client; chain ends | |
URL | same-site rewrite, 200, address bar unchanged | |
undefined / return; | skip this function; chain continues |
Endpoint
Redirect / rewrite
Rewrites must target the same site. To reach other sites, use fetch.
Middleware (modify origin response)
Call context.next() only when you need the response body. If you just return undefined, the chain continues on its own.
Conditional requests
By default, next() strips conditional headers, so it always returns a full response.
Read body, then continue
Netlify user gate (private / team-login-protected projects)
Post-response work
waitUntil does not block the response, but it still counts against the 50 ms CPU limit.
Streaming SSR (.tsx)
Context
| Property | Notes | ||
|---|---|---|---|
cookies.get(name) / .set(options) / `.delete(name \ | options)` | set and delete use CookieStore option format; they act on the outgoing response | |
geo | city, country.{code,name}, subdivision.{code,name}, latitude, longitude, timezone, postalCode (format varies) | ||
ip | client IP | ||
next(options?) / next(request, options?) | Promise<Response> from the next item in the chain | ||
params | URLPattern named groups from path (/pets/:name → { name }). For the query string, use request.url | ||
user | { id, email?, expiresAt } or undefined. It is a Netlify account, not Netlify Identity; for Identity, use getUser() from @netlify/identity | ||
waitUntil(promise) | runs after the response is sent | ||
requestId, account.id, server.region | — | ||
site | { id, name, url } | ||
deploy | { context, id, published, skewProtectionToken } |
Netlify adds no client-info headers to the request. Read client info from context instead.
Netlify.context gives the same object, but only inside the handler. Outside it, it is null.
Netlify.env: get(name), has(name), toObject(), and invocation-scoped set and delete. To change variables persistently, use the env API.
Web APIs:
console,atob,btoafetch,Request,Response,URL,File,BlobTextEncoder/TextDecoder(and their Stream variants),Performance- Web Crypto:
randomUUID,getRandomValues,SubtleCrypto - WebSocket
setTimeout,clearTimeout,setInterval- Streams:
ReadableStream,WritableStream,TransformStream - URLPattern
Modules:
- Node built-ins: use the
node:prefix (import { randomBytes } from "node:crypto"). - Deno modules: import by URL, or through an import map.
- npm packages (beta): import by name. Packages with native binaries or runtime dynamic imports may break.
Declarations
Inline config
| Key | Value | |||
|---|---|---|---|---|
path | URLPattern string or array; must start with / | |||
excludedPath | URLPattern string or array; must start with / | |||
pattern / excludedPattern | regex alternatives to path / excludedPath | |||
method | HTTP method string or array | |||
header | `{ name: true \ | false \ | "regex" }`; case-insensitive names; multi-value headers match the comma-joined list | |
onError | "fail" (default), "/custom-path", or "bypass" | |||
cache | "manual" |
The netlify-agent-category request header maps any user-agent to a client category.
netlify.toml
The toml form supports function, path, excludedPath, pattern, excludedPattern, [edge_functions.header], and cache. Set onError inline. Use toml when you need explicit ordering of several functions on one path.
A request to /admin runs auth, then common, then injector.
Order
Netlify walks the following order twice for the request path. The first pass runs only functions without caching configured. The second pass runs only cached functions.
- Framework-generated functions declared in a config file.
- Your
netlify.tomldeclarations, top to bottom. - Framework- and integration-generated inline declarations.
- Your inline declarations, alphabetical by file name.
If the same function is declared both in toml and inline, the configs are merged and treated as step 4; inline wins for duplicate fields.
After the edge functions, redirect rules run, unless a function already returned a Response. A redirect to a new path repeats the whole process for that path.
An edge function declared on the target of a static rewrite does not run for rewritten requests.
Response caching
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/netlify-edge-functions/SKILL.md
Popularity
- Repository stars
- 8
- Repository forks
- 2
- 7-day trend score
- 11
Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 16 Mar 2026, 7 months ago.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/netlify/context-and-tools/netlify-edge-functions)