Skip to content
Deployment
Skill

/netlify-functions

Write, configure, and deploy Netlify serverless functions in TypeScript, JavaScript, or Go. Use this when adding an API endpoint or backend route, adding a contact form handler, wiring auth or Identity signup/login hooks, identifying which Netlify user is calling a private or

From plugin
netlify-skills
5216 skills1 MCP

Claude Code

$ npx -y skills add netlify/context-and-tools --skill netlify-functions --agent claude-code

SKILL.md

netlify-functions.SKILL.md
name: netlify-functions
description: Write, configure, and deploy Netlify serverless functions in TypeScript, JavaScript, or Go. Use this when adding an API endpoint or backend route, adding a contact form handler, wiring auth or Identity signup/login hooks, identifying which Netlify user is calling a private or team-login-protected app, building streaming or AI-proxy responses, scheduling cron jobs, running long background jobs (batch processing/scraping), reacting to deploy or form events, setting up rate limiting or region/memory config, or reading environment variables and secrets inside a function. Covers file locations, the Request/Context/Response handler shape, path routing, config options, and local testing with netlify dev.

Netlify Functions

Reach for the modern default-handler API (`.mts` TypeScript). Export a default async handler taking a web `Request` and a Netlify `Context`, returning a web `Response`. Avoid the legacy AWS Lambda handler shape unless writing Go or migrating old code (see Legacy at the end).

File locations

  • Default directory: `netlify/functions/` (relative to base directory). Keep it **outside** your publish directory or source files ship as static assets.
  • A function is one file or a subdirectory whose entry file is named `index` or matches the subdirectory name. All of these create a function `hello`:
  • `netlify/functions/hello.mts`
  • `netlify/functions/hello/hello.mts`
  • `netlify/functions/hello/index.mts`
  • Use `.mts` (TS) / `.mjs` (JS) for ES modules. `.cts`/`.cjs` force CommonJS; `.ts`/`.js` follow the nearest `package.json` `"type"`.

⚠️ **Same-name JS and TS files: the JS one wins.** If the functions directory has e.g. `items.js` and `items.ts`, the JavaScript function is deployed and the TypeScript file is silently ignored — edits to the `.ts` have no effect. Keep one file per function name; delete or rename the stale `.js` when moving a function to TypeScript.

Minimal function

No `config` export. Serves at `/.netlify/functions/hello`.

import type { Context } from "@netlify/functions"

export default async (req: Request, context: Context) => {
  return new Response("Hello, world!")
}

Install types: `npm install @netlify/functions` (required for TS types; optional for JS).

Read env vars and secrets with `Netlify.env.get()`:

const apiKey = Netlify.env.get("STRIPE_SECRET_KEY")

Never hardcode secrets. For the variable to exist at runtime its scope must include **Functions**. Variables set in `netlify.toml` are NOT available to functions. Values are frozen per deploy — change them and redeploy to apply.

**Response headers are set in code** on the returned `Response`. `[[headers]]` in `netlify.toml`, `_headers`, and redirect header rules apply ONLY to static CDN responses, not function responses. Do not add CORS headers unless explicitly requested.

Custom path routing

Set `config.path` to route to custom URLs. When set, the function serves ONLY at that path — not at `/.netlify/functions/<name>`.

import type { Config, Context } from "@netlify/functions"

export default async (req: Request, context: Context) => {
  const { city, country } = context.params
  return new Response(`You're visiting ${city} in ${country}!`)
}

export const config: Config = {
  path: "/travel-guide/:city/:country",
}
  • Multiple paths: `path: ["/cats", "/dogs"]`.
  • Patterns: `path` supports [`URLPattern`](https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API) syntax — `path: ["/sale/*", "/item/:sku"]`. Named groups land on `context.params`. For the query string use `req.url`.
  • `excludedPath`: carve exceptions, e.g. `excludedPath: ["/product/*.css"]` with `path: "/product/*"`.
  • `preferStatic: true`: let a real static file at the URL win.
  • `method`: restrict methods, e.g. `method: ["GET", "POST"]`.

Fetchable module shape (alternative)

Equivalent to the default function; carries `config` inline and lets you add event handlers.

import type { NetlifyFunction } from "@netlify/functions"

export default {
  fetch: (req, context) => new Response("Hello, world!"),
  config: { path: "/hello" },
} satisfies NetlifyFunction

Context object

Second handler argument (or `getContext()` from `@netlify/functions` when out of handler scope — throws outside a request; wrap in try/catch).

  • `context.params` — named path params.
  • `context.geo` — `city`, `country.code/name`, `latitude`, `longitude`, `subdivision`, `timezone`, `postalCode`.
  • `context.ip` — client IP string.
  • `context.cookies` — `get(name)` / `set(options)` / `delete(name|options)`. Cross-subdomain cookies need a custom domain (`netlify.app` is on the Public Suffix List).
  • `context.site` — `id`, `name`, `url`. `context.deploy` — `context`, `id`, `published`, `skewProtectionToken`. `context.account.id`. `context.server.region`. `context.requestId`.
  • `context.user` — the Netlify user who logged in to a **private** or **team-login-protected** project: `id`, `email` (may be `undefined`), `expiresAt` (`Date`). See below.
  • `context.waitUntil(promise)` — run work after the response is sent (analytics, logs) without blocking. Billing/log duration counts until the promise settles. Available for functions deployed on/after 2025-03-20.

⚠️ `context.geo`/`context.ip` are **mocked** under `netlify dev` — test with `netlify dev --geo=mock --country=DE`.

Who is calling: `context.user`

⚠️ `context.user` is often `undefined`: public projects, basic password protection, local `netlify dev`, and functions deployed before October 5, 2026 (redeploy to enable). Always handle it; key records on `id` (`email` may be `undefined`).

import type { Config, Context } from "@netlify/functions"

export default async (req: Request, context: Context) => {
  if (!context.user) {
    // Public project, basic password protection, local CLI, o
Read more
@netlify
Ships withnetlify-skills

Public Netlify skills for AI coding agents. Each skill is a focused, factual reference for a Netlify platform primitive — designed to help agents build correctly on Netlify without needing to search docs.

5216 skills1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
52
Star history of netlify/context-and-tools on GitHub, a chart by star-history.com

Other skills on netlify-skills.

netlify-blobs

netlify-blobs

Store and retrieve unstructured objects, files, and cache-like state on Netlify with the @netlify/blobs module. Use when…

netlify-caching

netlify-caching

Cache dynamic and static responses on Netlify's CDN from Functions, Edge Functions, and proxies. Use when you add caching or…

netlify-config

netlify-config

Configure Netlify builds and routing via netlify.toml, _redirects, and _headers. Use when setting a build command or publish…

More skills from other plugins.

configuring-horizon

configuring-horizon

Use this skill whenever the user mentions Horizon by name in a Laravel context. Covers the full Horizon lifecycle: installing…

coolify13d66k
@coollabsio@coollabsioInstall Skill
vercel-cli

vercel-cli

Guides deployment, configuration, and troubleshooting with the Vercel CLI. Use when operating Vercel projects or resources…

vercel2w16k
@vercel@vercelInstall Skill
skypilot

skypilot

Use when launching cloud VMs, Kubernetes pods, or Slurm jobs for GPU/TPU/CPU workloads, training or fine-tuning models on cloud…

@skypilot-org@skypilot-orgInstall Skill
pinme

pinme

Use this skill when the user mentions "pinme", or needs to upload files, store to IPFS, create/publish/deploy websites or…

pinme2mo3.8k
@glitternetwork@glitternetworkInstall Skill

Questions about netlify-functions.

Which coding agents can use netlify-functions?
netlify-functions installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.