File-based configuration

In addition to using the Netlify UI to configure build settings, deploy settings, and environment variables, you can also configure these settings in a netlify.toml file stored in the root of your site repository. Settings specified in netlify.toml override any corresponding UI settings.

The netlify.toml file is a configuration file that specifies how Netlify builds and deploys your site — including redirects, branch and context-specific settings, and more. Its goal is to describe much of your site configuration alongside your code — with two goals:

  • When someone forks your repository, they can instantly create a Netlify site using the new repo. They don’t have to configure anything in the UI, and they’ll still get an identical site configuration.
  • You can track configuration changes using version control and configure some things that aren’t customizable in our UI.

There are other ways to accomplish some of the things you would use the netlify.toml file for. For example, you can use _headers and _redirects files to accomplish what the filename suggests, but having these settings all live in the same file can greatly simplify maintaining them.

The following sections will go through each thing you’ll be able to do in the netlify.toml file and some examples that you could use in your code. For more information on TOML syntax, visit the TOML website.

# Sample file

This sample netlify.toml file demonstrates many settings available for configuration.

# Settings in the [build] context are global and are applied to all contexts
# unless otherwise overridden by more specific contexts.
  # Directory to change to before starting a build.
  # This is where we will look for package.json/.nvmrc/etc.
  # If not set, defaults to the root directory.
  base = "project/"

  # Directory that contains the deploy-ready HTML files and assets generated by
  # the build. This is relative to the base directory if one has been set, or the
  # root directory if a base has not been set. This sample publishes the
  # directory located at the absolute path "root/project/build-output"
  publish = "build-output/"

  # Default build command.
  command = "echo 'default context'"

# Production context: all deploys from the Production branch set in your site’s
# deploy contexts will inherit these settings.
  publish = "output/"
  command = "make publish"
  environment = { ACCESS_TOKEN = "super secret", NODE_VERSION = "14.15.3" }

# Deploy Preview context: all deploys generated from a pull/merge request will
# inherit these settings.
  publish = "dist/"

# Here is another way to define context specific environment variables.
  ACCESS_TOKEN = "not so secret"

# Branch Deploy context: all deploys that are not from a pull/merge request or
# from the Production branch will inherit these settings.
  command = "echo branch"
  NODE_ENV = "development"

# Specific branch context: all deploys from this specific branch will inherit
# these settings.
[context.staging] # “staging” is a branch name
  command = "echo 'staging'"
  base = "staging"

# For contexts of branches with special characters, enclose the branch name
# with quotes.
  command = "echo 'special branch'"
  base = "branch"

# Redirects and headers are GLOBAL for all builds – they do not get scoped to
# contexts no matter where you define them in the file.
# For context-specific rules, use _headers or _redirects files, which are

# A basic redirect rule
  from = "/*"
  to = "/blog/:splat"

# A redirect rule with many of the supported properties
  from = "/old-path"
  to = "/new-path"

  # The default HTTP status code is 301, but you can define a different one.
  status = 302

  # By default, redirects won’t be applied if there’s a file with the same
  # path as the one defined in the `from` property. Setting `force` to `true`
  # will make the redirect rule take precedence over any existing files.
  force = true

  # Redirect from /old-path?id=123 to /new-path. Each combination of query
  # params needs to be defined in a separate [[redirects]] block.
  # More information at
  query = {id = ":id"}

  # Redirect based on browser language and geolocation.
  conditions = {Language = ["en"], Country = ["US"]}

  # Sign each request with a value defined in an environment variable

  # You can also define custom headers within your redirects blocks.
    X-From = "Netlify"
    X-Api-Key = "some-api-key-string"

# Role-based redirects do not have a “to” property.
  from = "/gated-path"
  status = 200
  conditions = {Role = ["admin"]}
  force = true

# The following redirect is intended for use with most SPAs that handle
# routing internally.
  from = "/*"
  to = "/index.html"
  status = 200

  # Define which paths this specific [[headers]] block will cover.
  for = "/*"

    X-Frame-Options = "DENY"
    X-XSS-Protection = "1; mode=block"
    Content-Security-Policy = "frame-ancestors"

    # Multi-value headers are expressed with multi-line strings.
	cache-control = '''

    # Basic-Auth allows you to password protect your whole site.
    # This feature may not be available on all plans.
    Basic-Auth = "someuser:somepassword anotheruser:anotherpassword"

  # Directory with serverless functions, including background functions,
  # to deploy. This is relative to the base directory if one has been set, 
  # or the root directory if a base hasn’t been set.
  directory = "functions/"

# Configuration details

The following sections provide additional detail for some commonly used configuration settings.

# Build settings

[build] has a number of properties (keys) that you can set. Here’s a list of them:

  • base
  • publish
  • command
  • environment
  • processing
  • edge_handlers

If a key has a list of key/value pairs as its value, you can set that key in its own block like this:

  VARIABLE = "value"

# Ignore builds

For sites connected to a Git repo after October 3rd, 2019, Netlify tries to determine if there are any changes in the site’s base directory by comparing the last known version of the files within that directory. If no change was detected, the build system skips the build, returning early from the build process.

If you would like to override the default check with a custom workflow you can use the ignore attribute in netlify.toml which allows you to specify a unix shell command that will be run from the base directory to determine whether you consider the site to need rebuilding or not.

For sites created before October 3rd, 2019

If you would like to use this feature for a site that was created before October 3rd, 2019, you’ll need to re-link your repository to make this feature available for your site.

An exit-code of 1 indicates the contents have changed, so if your command returns that code the build process will continue per usual. An exit-code of 0 indicates that the build should return early.

  ignore = "git diff --quiet HEAD^ HEAD sub_dir/"

# Deploy contexts

Certain keys, such as [build] and [[plugins]] but not [[redirects]] or [[headers]], allow you to set [context] properties based on the kind of deploy. These keys are context-aware.

During a build, the following ordering determines which context covers a particular deploy:

  • UI settings are overridden if a netlify.toml file is present in the root folder of the repo and there exists a setting for the same property/redirect/header in the toml file.
  • any property of a context-aware key, such as [build] or [[plugins]], will be applied to all contexts unless the same property key is present in a more specific context.
  • any property in [context.production], [context.deploy-preview] or [context.branch-deploy] will override less specific contexts:
    • production — a deploy generated from the production branch set in the UI
    • deploy-preview — a deploy generated from a pull request or merge request
    • branch-deploy — a deploy generated from a branch that is not your production branch
  • any property in [context.branchname], for a given branchname, is the most specific, and thus overrides all the less specific contexts.

# Post processing

You can manage post processing settings with the processing property. These settings override corresponding settings under Site settings > Build & deploy > Post processing > Asset Optimization.

When declaring post processing settings, you can use the processing property on build to define settings for each post processing option. Note that skip_processing must be set to false for any other settings to take effect.

# If skip_processing = true, all other settings are ignored
  skip_processing = false
  bundle = true
  minify = false
  bundle = true
  minify = false
  pretty_urls = true
  compress = true

You can also control post processing settings per deploy context.

# Skip all post processing in deploy previews,
# ignoring any other settings
  skip_processing = true

  skip_processing = false
  compress = false

# Redirects

You can manage your redirects directly in your netlify.toml file. When declaring redirects, use an array of values in a section with the [[redirects]] heading:

  from = "/old-path"
  to = "/new-path"
  status = 301
  force = false
  query = {path = ":path"} #  apply this rule for /old-path?path=example
  conditions = {Language = ["en","es"], Country = ["US"]}

Here’s a proxy redirect:

  from = "/api/*"
  to = ""
  status = 200
  force = true
  conditions = {Role = ["admin", "cms"]}
    X-From = "Netlify"
    X-Api-Key = "some-api-key-string"

You can redirect your netlify subdomain to your custom domain. Note that the force = true is equivalent to the ! (for shadowing) in the _redirects file:

  from = ""
  to = ""
  status = 301
  force = true

Here’s a redirect rule with an Edge Handler:

  from = "/*"
  to = "/:splat"
  status = 200
  edge_handler = "filterRequests"

# Headers

You can define custom headers like this:

  for = "/*"
    X-Frame-Options = "DENY"
    X-XSS-Protection = "1; mode=block"

    #  Multi-value headers are expressed with multi-line strings
	cache-control = '''

    # The Basic-Auth header may not be available on all plans.
    Basic-Auth = "someuser:somepassword anotheruser:anotherpassword"

# Functions

Although there are default settings for Netlify Functions to help you get started, you can use the [functions] section in netlify.toml for custom configuration.

[functions] has the following optional properties:

  • directory: a custom path to your serverless functions. The default location is YOUR_BASE_DIRECTORY/netlify/functions.
  • node_bundler: the function bundling method used in @netlify/zip-it-and-ship-it for JavaScript and TypeScript serverless functions. You can set the property for all Netlify Functions in a project or filter them by name, including filtering using a wildcard pattern. Valid values:
    • zisi: the default function bundling method for JavaScript serverless functions.
    • esbuild: leverages esbuild to bundle functions, resulting in shorter bundling times and smaller artifacts. Currently available as an opt-in beta for JavaScript functions. TypeScript serverless functions always use esbuild.
  • external_node_modules: a list of Node.js modules that are copied to the bundled artifact without adjusting their source or references during the bundling process. This setting only applies when node_bundler is set to esbuild, and it’s compatible with JavaScript and TypeScript serverless functions. external_node_modules helps handle dependencies that can’t be inlined, such as modules with native add-ons. You can set it for all Netlify Functions in your project or filter them by name, including using a wildcard pattern. If a function matches several configuration blocks containing an external_node_modules property, the arrays are concatenated.
  # Sets a custom directory for Netlify Functions
  directory = "myfunctions/"

  # Specifies `esbuild` for functions bundling
  node_bundler = "esbuild"
  # Flags "package-1" as an external node module for all functions
  external_node_modules = ["package-1"]

  # Flags "package-2" as an external node module for functions with a name beginning with "api_".
  # Functions matching this pattern have both "package-1" and "package-2" as external modules,
  # because modules from this object are concatenated with any from the top-level object.
  external_node_modules = ["package-2"]

  # Flags "package-3" and "package-4" as external node modules for a function named "api_payment".
  # This function has 4 external node modules:
  #  "package-1" from the top-level object
  #  "package-2" from the "api_*" object
  #  "package-3" and "package-4" from this object
  external_node_modules = ["package-3", "package-4"]

# Edge Handlers

Although you declare Edge Handlers in the redirects section of netlify.toml, you can use the build setting to set a custom path to your Edge Handlers directory:

[build] # Make sure you don’t have a duplicate [build] context!
  edge_handlers = "src/my-edge-handlers"

# Netlify Dev

Netlify Dev uses detectors to enable a local development environment for most tools and frameworks without any additional setup. However, you can use the [dev] section in netlify.toml for optional configuration. Netlify Dev also makes use of the Functions directory setting to scaffold and serve your Functions in a local development environment.

[dev] has the following optional properties:

  • command: the command that starts your development server.
  • port: the port that Netlify Dev is accessible from in the browser.
  • targetPort: the port for your application server, framework, or site generator. If you specify values for both command and targetPort, framework must be #custom.
  • publish: the path to your static content folder.
  • jwtRolePath: the object path that points to role values for JWT-based redirects.
  • jwtSecret: the secret used to verify tokens for JWT-based redirects.
  • autoLaunch: a boolean value that determines whether Netlify Dev launches the local server address in your browser.
  • framework: setting to use if a project is detected incorrectly, flagged by multiple detectors, or requires a command and targetPort. Valid values:
    • #auto: the default, tests all available detectors.
    • #static: specifies a static file server.
    • #custom: uses the command value to run an app server and the targetPort value to connect to it. Required if command and targetPort are both set.
  • https: specifies an SSL/TLS certificate and key file for the Netlify Dev local server. By default, Netlify Dev starts an HTTP server, but you can configure a certificate and key file if you require HTTPS. The https configuration is an object with the following properties:
    • certFile: the path to the certificate file.
    • keyFile: the path to the private key file.

Here’s an example [dev] section for Netlify Dev configuration overrides:

  command = "yarn start"
  port = 8888
  targetPort = 3000
  publish = "dist" 
  jwtRolePath = "app_metadata.authorization.roles"
  jwtSecret = "MY_JWT_SECRET_VALUE"
  autoLaunch = true
  framework = "#custom"
    certFile = "cert.pem"
    keyFile = "key.pem"

# Inject environment variable values

Using environment variables directly as values ($VARIABLENAME) in your netlify.toml file is not supported. However, the following workflow can be used to substitute values in the file with environment variable values, assuming you are only trying to change headers or redirects. The rest of the file is read BEFORE your build — but those sections are read AFTER the build process.

  1. Add a placeholder like HEADER_PLACEHOLDER somewhere in the netlify.toml redirects or headers sections.
  2. Create an environment variable, for example PROD_API_LOCATION, with the desired value. You can create environment variables in the toml file or in our UI. You might use the latter to keep sensitive values out of your repository.
  3. Prepend a replacement command to your build command. Here’s an example for a site using yarn build to build:
    sed -i "s|HEADER_PLACEHOLDER|${PROD_API_LOCATION}|g" netlify.toml && yarn build