netlify/context-and-tools1 file

Netlify Config

Configure Netlify builds and routing via netlify.toml, _redirects, and _headers. Use when setting a build command or publish directory, adding redirects or rewrites or proxies, adding an SPA fallback rewrite, setting custom response headers or basic auth, managing environment variables and secrets, scoping vars per deploy context, marking a var as secret, disabling secret scanning, configuring functions bundling, ignoring builds, or wiring up a monorepo or JavaScript SPA on Netlify.

Specification
Skill ID
netlify/context-and-tools/netlify-config
Publisher
netlify
Repository
context-and-tools
Installs
0
Files
1
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

netlify/context-and-tools/netlify-configInstalls these files
  • SKILL.md

What this skill tells the agent

Netlify configuration

Config lives in three files at the repo root (or the base/package directory for monorepos):

  • netlify.toml — build, contexts, plugins, functions, redirects, headers, dev.
  • _redirects — plain-text redirect/rewrite rules, saved to the publish directory, no extension.
  • _headers — plain-text response headers, saved to the publish directory.

netlify.toml values take precedence over the Netlify UI when they conflict. Paths in netlify.toml are absolute relative to the base directory (root / by default).

Modern vs legacy syntax to reach for

  • Functions bundler: use node_bundler = "esbuild". zisi is the legacy JS default; TypeScript always uses esbuild.
  • Temporary redirect: use status = 302. 307 is unsupported.
  • Gatsby Image CDN: use NETLIFY_IMAGE_CDN, not the deprecated GATSBY_CLOUD_IMAGE_CDN.
  • Injecting env values into TOML: key = "$VAR" is NOT supported (except signed in proxy redirects). Use a build-command sed substitution or a build plugin (see below).

netlify.toml build + contexts

[build]
  base = "frontend"
  publish = "dist"
  command = "npm run build"
  environment = { NODE_VERSION = "18" }

[context.production]
  publish = "output/"
  command = "make publish"

[context.deploy-preview]
  publish = "dist/"

[context."feat/branch"]        # quote names with special characters
  command = "npm run preview"

[build] runs in Bash. Context-aware keys include [build] and [[plugins]] — but NOT [[redirects]] or [[headers]] (those are always global). Precedence, least→most specific: UI < toml < any-context property < [context.<name>] < [context.branchname].

Redirects and rewrites

_redirects rules are processed first, then netlify.toml; within each, the first matching rule top-to-bottom wins — list specific rules before general ones. Edge functions run before redirects.

SPA history-pushState fallback (required for clean URLs):

/*  /index.html  200
[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

_redirects syntax — from to [status] [conditions], # comments, paths case-sensitive, URL-encode special chars:

/home         /              301
/my-redirect  /              302
/ecommerce    /store-closed  404          # custom 404 for a path
/pass-through /index.html    200          # rewrite
/best-pets/dogs /best-pets/cats.html 200! # force/shadow (! or force=true)
/news/*  /blog/:splat                     # splat
/news/:month/:date/:year/:slug  /blog/:year/:month/:date/:slug   # placeholders
/store id=:id  /blog/:id  301             # query params
/  /anz  302  Country=au,nz               # no spaces in value list
/israel/*  /israel/he/:splat  302  Language=he
/* /legacy/:splat 200 Cookie=is_legacy,my_other_cookie

[[redirects]] keywords: from, to, status (default 301), force (default false; !/shadow), query (query = {path = ":path"}), conditions ({Language, Country, Role, Cookie}), headers (proxy request headers), signed (env var name for signed proxies).

Gotchas:

  • You cannot add/remove a trailing slash with a redirect — CDN normalizes URLs first; a /x/ → /x 301! rule loops infinitely. Rely on Pretty URLs (default on).
  • Splat asterisks work only at the end of a segment (/jobs/*), not mid-path (/jobs/*.html invalid). Placeholders (:x) only at the start of a segment; can't mix wildcard+placeholder in one segment.
  • You can't exclude a path from a splat; put a more specific rule first.
  • Country = ISO 3166-1 alpha-2; language redirects match only the first Accept-Language entry.
  • Role-based redirects with external auth providers are Enterprise-only.
  • 10,000+ redirects: use wildcards/placeholders or Edge Functions — oversized serialized output fails the deploy.

Proxies

/api/*           https://api.example.com/:splat        200
/netlify-site/*  https://my-other-site.netlify.app/:splat  200   # use .netlify.app, not custom domain
[[redirects]]                     # custom request headers + force
  from = "/search"
  to = "https://api.mysearch.com"
  status = 200
  force = true
  headers = {X-From = "Netlify"}

Signed proxy (signed names an env var scoped to Runtime; must live in netlify.toml; JWS is external-only, not Netlify→Netlify):

[[redirects]]
  from = "/search"
  to = "https://api.mysearch.com"
  status = 200
  force = true
  signed = "API_SIGNATURE_TOKEN_PLACEHOLDER"

Gotchas: cross-team rewrites disallowed; same-password-site rewrites OK but not across separate protected sites; proxy timeout 26 s; one hop by default; relative-path assets break (use absolute or <base>); loops silently ignored.

Custom headers

/*
  X-Frame-Options: DENY
/templates/index2.html
  X-Frame-Options: SAMEORIGIN

Multi-value — repeat the key (_headers) or a multiline TOML string:

[[headers]]
  for = "/*"
  [headers.values]
  cache-control = '''
  max-age=0,
  no-cache,
  no-store,
  must-revalidate'''

Gotchas:

  • Headers in _headers/netlify.toml are global — NOT scoped to branch/context. Workaround: strip global headers, keep header files in a custom dir, and cp them into the publish dir from a per-context build command: ``toml [context.staging] command = "npm run build && cp ./custom-headers/_stagingHeaders ./dist/_headers" ``
  • Headers apply only to files from Netlify's store — NOT to proxied content or function/edge (SSR) responses; those must set their own headers.
  • Ignored (server-set) names include Content-Length, Content-Encoding, Location (use redirects), Set-Cookie, Server, etc.
  • Basic auth headers: Pro/Enterprise only. Cross-subdomain cookies need a custom domain (netlify.app is on the Public Suffix List).

Functions

[functions]
  directory = "myfunctions/"          # default: <base>/netlify/functions
  node_bundler = "esbuild"
  external_node_modules = ["package-1"]  # esbuild only; native add-ons etc.
  included_files = ["files/*.md"]        # ! prefix excludes

[functions."api_*"]                    # glob/named blocks concatenate with top-level
  external_node_modules = ["package-2"]
  included_files = ["!files/post-1.md"]

Environment variables

Two storage methods:

  • UI / CLI / API — stored on Netlify (not the repo). Supports site + shared vars, per-context values, scopes; reaches builds, functions/edge/ODB, snippet injection, forms, signed proxies. Recommended for anything sensitive.
  • `netlify.toml` — stored in the repo. Site vars only, per-context values, no scope selection (everything gets Builds + Post processing), reaches builds + snippet injection only.

netlify.toml env vars override same-key UI/CLI/API vars.

Per-context values in TOML:

[context.production]
  environment = { NODE_VERSION = "14.15.3" }
[context.deploy-preview.environment]
  NOT_PRIVATE_ITEM = "not so secret"
[context.branch-deploy.environment]
  NODE_ENV = "development"

CLI:

netlify env:set KEY value          # --secret marks it a secret
netlify env:import .env             # site vars; --replace-existing wipes others first
netlify env:unset KEY
netlify env:list --plain --context production > .env
netlify build                       # local build with Netlify's env vars

API: createEnvVars / updateEnvVar (is_secret: true) / setEnvVarValue / deleteEnvVar / deleteEnvVarValue.

Access syntax: Bash $VAR in build.command/ignore.command; process.env.VAR in Node scripts and plugins.

More from netlify

Use this skill in a project

Open any RiverX project, search the Skills panel for netlify/context-and-tools/netlify-config, and install it in one click.

Use this skill