Static Configuration with vercel.json

Skip to content

Project Configuration

vercel.json

Copy pageCopy page

On this page

Static Configuration with vercel.json

Copy pageCopy page

The vercel.json file lets you configure, and override the default behavior of Vercel from within your project.

This file should be created in your project's root directory and allows you to set:

schema autocomplete Copy link to section

To add autocompletion, type checking, and schema validation to your vercel.json file, add the following to the top of your file:

{
  "$schema": "https://openapi.vercel.sh/vercel.json"
}

buildCommand Copy link to section

Type:string | null

The buildCommand property can be used to override the Build Command in the Project Settings dashboard, and the build script from the package.json file for a given deployment. For more information on the default behavior of the Build Command, visit the Configure a Build - Build Command section.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "buildCommand": "next build"
}

This value overrides the Build Command in Project Settings.

bunVersion Copy link to section

The Bun runtimeis available in Betaon all plans

Type:string

Value:"1.4.x" | "1.x"

The bunVersion property configures your project to use the Bun runtime instead of Node.js. When set, all Vercel Functions and Routing Middleware not using the Edge runtime will run using the specified Bun version.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "bunVersion": "1.4.x"
}

Vercel manages the Bun minor versions automatically. 1.4.x and 1.x are the only valid values currently.

When using Next.js with ISR (Incremental Static Regeneration), you must also update your build and dev commands in package.json:

package.json

{
  "scripts": {
    "dev": "bun run --bun next dev",
    "build": "bun run --bun next build"
  }
}

To learn more about using Bun with Vercel Functions, see the Bun runtime documentation.

cleanUrls Copy link to section

Type: Boolean.

Default Value: false.

When set to true, all HTML files and Vercel functions will have their extension removed. When visiting a path that ends with the extension, a 308 response will redirect the client to the extensionless path.

For example, a static file named about.html will be served when visiting the /about path. Visiting /about.html will redirect to /about.

Similarly, a Vercel Function named api/user.go will be served when visiting /api/user. Visiting /api/user.go will redirect to /api/user.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "cleanUrls": true
}

If you are using Next.js and running vercel dev, you will get a 404 error when visiting a route configured with cleanUrls locally. It does however work fine when deployed to Vercel. In the example above, visiting /about locally will give you a 404 with vercel dev but /about will render correctly on Vercel.

crons Copy link to section

Used to configure cron jobs for the production deployment of a project.

Type: Array of cron Object.

Limits:

Cron object definition Copy link to section

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "crons": [\
    {\
      "path": "/api/every-minute",\
      "schedule": "* * * * *"\
    },\
    {\
      "path": "/api/every-hour",\
      "schedule": "0 * * * *"\
    },\
    {\
      "path": "/api/every-day",\
      "schedule": "0 0 * * *"\
    }\
  ]
}

devCommand Copy link to section

This value overrides the Development Command in Project Settings.

Type:string | null

The devCommand property can be used to override the Development Command in the Project Settings dashboard. For more information on the default behavior of the Development Command, visit the Configure a Build - Development Command section.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "devCommand": "next dev"
}

fluid Copy link to section

This value allows you to enable Fluid compute programmatically.

Type:boolean | null

The fluid property allows you to test Fluid compute on a per-deployment or per custom environment basis when using branch tracking, without needing to enable Fluid in production.

As of April 23, 2025, Fluid compute is enabled by default for new projects.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "fluid": true
}

framework Copy link to section

This value overrides the Framework in Project Settings.

Type:string | null

Available framework slugs:

nextjs nuxtjs svelte create-react-app gatsby remix react-router solidstart sveltekit container blitzjs astro hexo eleventy docusaurus-2 docusaurus preact solidstart-1 dojo ember vue scully ionic-angular angular polymer sveltekit-1 ionic-react gridsome umijs sapper saber stencil redwoodjs hugo jekyll brunch middleman zola hydrogen vite tanstack-start tanstack-start-lovable vitepress vuepress parcel fastapi flask fasthtml django factory-eveeve sanity sanity-v2 storybook nitro hono express h3 koa nestjs elysia fastify xmcp python node go services mastra

The framework property can be used to override the Framework Preset in the Project Settings dashboard. The value must be a valid framework slug. For more information on the default behavior of the Framework Preset, visit the Configure a Build - Framework Preset section.

To select "Other" as the Framework Preset, use null.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "framework": "nextjs"
}

functions Copy link to section

Type:Object of key String and value Object.

Key definition Copy link to section

A glob pattern that matches the paths of the Vercel functions you would like to customize:

Value definition Copy link to section

Description Copy link to section

By default, no configuration is needed to deploy Vercel functions to Vercel.

For all officially supported runtimes, the only requirement is to create an api directory at the root of your project directory, placing your Vercel functions inside.

The functions property cannot be used in combination with builds. Since the latter is a legacy configuration property, we recommend dropping it in favor of the new one.

Because Incremental Static Regeneration (ISR) uses Vercel functions, the same configurations apply. The ISR route can be defined using a glob pattern, and accepts the same properties as when using Vercel functions.

When deployed, each Vercel Function uses your project's default memory and maximum duration. See Vercel Functions limits for plan limits and defaults.

With Fluid compute enabled, set memory in the Functions section of your project dashboard, not in vercel.json. To override the maximum duration for matched functions, add the functions property.

functions property with Vercel functions Copy link to section

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "functions": {
    "api/test.js": {
      "maxDuration": 30
    },
    "api/*.js": {
      "maxDuration": 30
    }
  }
}

functions property with ISR Copy link to section

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "functions": {
    "pages/blog/[hello].tsx": {
      "maxDuration": 5
    },
    "src/pages/isr/**/*": {
      "maxDuration": 10
    }
  }
}

Per-function regions and functionFailoverRegions Copy link to section

You can set regions and functionFailoverRegions on individual functions to override the project-level defaults. This is useful when different functions need to run in different regions, for example when they access different data sources.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "regions": ["iad1"],
  "functions": {
    "api/eu-data.js": {
      "regions": ["cdg1"],
      "functionFailoverRegions": ["lhr1"]
    },
    "api/us-data.js": {
      "regions": ["sfo1", "iad1"],
      "functionFailoverRegions": ["pdx1"]
    }
  }
}

In the example above, api/eu-data.js runs in Paris (cdg1) with London (lhr1) as a failover, while api/us-data.js runs in San Francisco (sfo1) and Washington, D.C. (iad1) with Portland (pdx1) as a failover. All other functions use the project-level default of iad1.

Using unsupported runtimes Copy link to section

To use a runtime that is not officially supported, you can add a runtime property to the definition:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "functions": {
    "api/test.php": {
      "runtime": "vercel-php@0.5.2"
    }
  }
}

In the example above, the api/test.php Vercel Function does not use one of the officially supported runtimes. In turn, a runtime property was added to invoke the vercel-php community runtime.

For more information on Runtimes, see the Runtimes documentation:

headers Copy link to section

Type:Array of header Object.

Valid values: a list of header definitions.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "headers": [\
    {\
      "source": "/service-worker.js",\
      "headers": [\
        {\
          "key": "Cache-Control",\
          "value": "public, max-age=0, must-revalidate"\
        }\
      ]\
    },\
    {\
      "source": "/(.*)",\
      "headers": [\
        {\
          "key": "X-Content-Type-Options",\
          "value": "nosniff"\
        },\
        {\
          "key": "X-Frame-Options",\
          "value": "DENY"\
        },\
        {\
          "key": "X-XSS-Protection",\
          "value": "1; mode=block"\
        }\
      ]\
    },\
    {\
      "source": "/:path*",\
      "has": [\
        {\
          "type": "query",\
          "key": "authorized"\
        }\
      ],\
      "headers": [\
        {\
          "key": "x-authorized",\
          "value": "true"\
        }\
      ]\
    }\
  ]
}

This example configures custom response headers for static files, Vercel functions, and a wildcard that matches all routes.

Header object definition Copy link to section

Property Description
source A pattern that matches each incoming pathname (excluding querystring).
headers A non-empty array of key/value pairs representing each response header.
has An optional array of has objects with the type, key and value properties. Used for conditional path matching based on the presence of specified properties.
missing An optional array of missing objects with the type, key and value properties. Used for conditional path matching based on the absence of specified properties.

Header has or missing object definition Copy link to section

Property Type Description
type String Must be either header, cookie, host, or query. The type property only applies to request headers sent by clients, not response headers sent by your functions or backends.
key String The key from the selected type to match against. For example, if the type is header and the key is X-Custom-Header, we will match against the X-Custom-Header header key.
value String or Object or undefined The value to check for, if undefined any value will match. A regex like string can be used to capture a specific part of the value. For example, if the value first-(?<paramName>.*) is used for first-second then second will be usable in the destination with :paramName. If an object is provided, it will match when all conditions are met for its fields below.

If value is an object, it has one or more of the following fields:

Condition Type Description
eq String (optional) Check for equality
neq String (optional) Check for inequality
inc Array<String> (optional) Check for inclusion in the array
ninc Array<String> (optional) Check for non-inclusion in the array
pre String (optional) Check for prefix
suf String (optional) Check for suffix
re String (optional) Check for a regex match
gt Number (optional) Check for greater than
gte Number (optional) Check for greater than or equal to
lt Number (optional) Check for less than
lte Number (optional) Check for less than or equal to

This example demonstrates using the expressive value object to append the header x-authorized: true if the X-Custom-Header request header's value is prefixed by valid and ends with value.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "headers": [\
    {\
      "source": "/:path*",\
      "has": [\
        {\
          "type": "header",\
          "key": "X-Custom-Header",\
          "value": {\
            "pre": "valid",\
            "suf": "value"\
          }\
        }\
      ],\
      "headers": [\
        {\
          "key": "x-authorized",\
          "value": "true"\
        }\
      ]\
    }\
  ]
}

Learn more about headers on Vercel and see limitations.

ignoreCommand Copy link to section

This value overrides the Ignored Build Step in Project Settings.

Type:string | null

This ignoreCommand property will override the Command for Ignoring the Build Step for a given deployment. When the command exits with code 1, the build will continue. When the command exits with 0, the build is ignored. For more information on the default behavior of the Ignore Command, visit the Ignored Build Step section.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "ignoreCommand": "git diff --quiet HEAD^ HEAD ./"
}

installCommand Copy link to section

This value overrides the Install Command in Project Settings.

Type:string | null

The installCommand property can be used to override the Install Command in the Project Settings dashboard for a given deployment. This setting is useful for trying out a new package manager for the project. An empty string value will cause the Install Command to be skipped. For more information on the default behavior of the install command visit the Configure a Build - Install Command section.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "installCommand": "npm install"
}

images Copy link to section

The images property defines the behavior of Vercel's native Image Optimization API, which allows on-demand optimization of images at runtime.

Type: Object

Value definition Copy link to section

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "images": {
    "sizes": [256, 640, 1080, 2048, 3840],
    "localPatterns": [{\
      "pathname": "^/assets/.*$",\
      "search": ""\
    }],
    "remotePatterns": [\
      {\
        "protocol": "https",\
        "hostname": "example.com",\
        "port": "",\
        "pathname": "^/account123/.*$",\
        "search": "?v=1"\
      }\
    ],
    "minimumCacheTTL": 60,
    "qualities": [25, 50, 75],
    "formats": ["image/webp"],
    "dangerouslyAllowSVG": false,
    "contentSecurityPolicy": "script-src 'none'; frame-src 'none'; sandbox;",
    "contentDispositionType": "inline"
  }
}

outputDirectory Copy link to section

This value overrides the Output Directory in Project Settings.

Type:string | null

The outputDirectory property can be used to override the Output Directory in the Project Settings dashboard for a given deployment.

In the following example, the deployment will look for the build directory rather than the default public or . root directory. For more information on the default behavior of the Output Directory see the Configure a Build - Output Directory section. The following example is a vercel.json file that overrides the outputDirectory to build:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "outputDirectory": "build"
}

proxy Copy link to section

Type:Object

The proxy property can be used to explicitly configure the file Vercel builds as Routing Middleware. Without it, Vercel looks for a middleware.ts or middleware.js file at your project root.

Value definition Copy link to section

Description Copy link to section

The following configuration builds proxy.ts as your Routing Middleware and runs it on requests under /api:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "proxy": {
    "entrypoint": "proxy.ts",
    "matcher": "/api/:func*"
  }
}

Your entrypoint exports the handler as a default export:

proxy.ts

export default function proxy(request: Request) {
  return new Response('Hello from your Routing Middleware!');
}

proxy.js

export default function proxy(request) {
  return new Response('Hello from your Routing Middleware!');
}

Runtime Copy link to section

An entrypoint configured through proxy runs on the Node.js runtime.

A middleware.ts file that sets runtime: 'nodejs' in its exported config behaves the same as "proxy": { "entrypoint": "middleware.ts" }.

Setting the matcher Copy link to section

You can set either proxy.matcher in vercel.json, or export a config object with a matcher property from your entrypoint.

The matcher accepts a single path or an array of paths:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "proxy": {
    "entrypoint": "src/proxy.ts",
    "matcher": ["/about/:path*", "/dashboard/:path*"]
  }
}

Without a matcher, your Routing Middleware runs on every request.

Setting function options Copy link to section

Set duration, memory, and other per-function options with the functions property, keyed on your entrypoint path:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "proxy": {
    "entrypoint": "proxy.ts"
  },
  "functions": {
    "proxy.ts": {
      "maxDuration": 10
    }
  }
}

redirects Copy link to section

Type:Array of redirect Object.

Valid values: a list of redirect definitions.

Redirects examples Copy link to section

Some redirects and rewrites configurations can accidentally become gateways for semantic attacks. Learn how to check and protect your configurations with the Enhancing Security for Redirects and Rewrites guide.

This example redirects requests to the path /me from your site's root to the profile.html file relative to your site's root with a 307 Temporary Redirect:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "redirects": [\
    { "source": "/me", "destination": "/profile.html", "permanent": false }\
  ]
}

This example redirects requests to the path /me from your site's root to the profile.html file relative to your site's root with a 308 Permanent Redirect:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "redirects": [\
    { "source": "/me", "destination": "/profile.html", "permanent": true }\
  ]
}

This example redirects requests to the path /user from your site's root to the api route /api/user relative to your site's root with a 301 Moved Permanently:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "redirects": [\
    { "source": "/user", "destination": "/api/user", "statusCode": 301 }\
  ]
}

This example redirects requests to the path /view-source from your site's root to the absolute path https://github.com/vercel/vercel of an external site with a redirect status of 308:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "redirects": [\
    {\
      "source": "/view-source",\
      "destination": "https://github.com/vercel/vercel"\
    }\
  ]
}

This example redirects requests to all the paths (including all sub-directories and pages) from your site's root to the absolute path https://vercel.com/docs of an external site with a redirect status of 308:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "redirects": [\
    {\
      "source": "/(.*)",\
      "destination": "https://vercel.com/docs"\
    }\
  ]
}

This example uses wildcard path matching to redirect requests to any path (including subdirectories) under /blog/ from your site's root to a corresponding path under /news/ relative to your site's root with a redirect status of 308:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "redirects": [\
    {\
      "source": "/blog/:path*",\
      "destination": "/news/:path*"\
    }\
  ]
}

This example uses regex path matching to redirect requests to any path under /posts/ that only contain numerical digits from your site's root to a corresponding path under /news/ relative to your site's root with a redirect status of 308:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "redirects": [\
    {\
      "source": "/post/:path(\\d{1,})",\
      "destination": "/news/:path*"\
    }\
  ]
}

This example redirects requests to any path from your site's root that does not start with /uk/ and has x-vercel-ip-country header value of GB to a corresponding path under /uk/ relative to your site's root with a redirect status of 307:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "redirects": [\
    {\
      "source": "/:path((?!uk/).*)",\
      "has": [\
        {\
          "type": "header",\
          "key": "x-vercel-ip-country",\
          "value": "GB"\
        }\
      ],\
      "destination": "/uk/:path*",\
      "permanent": false\
    }\
  ]
}

Using has does not yet work locally while using vercel dev, but does work when deployed.

Redirect object definition Copy link to section

Property Description
source A pattern that matches each incoming pathname (excluding querystring).
destination A location destination defined as an absolute pathname or external URL.
permanent An optional boolean to toggle between permanent and temporary redirect (default true). When true, the status code is 308. When false the status code is 307.
statusCode An optional integer to define the status code of the redirect. Used when you need a value other than 307/308 from permanent, and therefore cannot be used with permanent boolean.
has An optional array of has objects with the type, key and value properties. Used for conditional redirects based on the presence of specified properties.
missing An optional array of missing objects with the type, key and value properties. Used for conditional redirects based on the absence of specified properties.

Redirect has or missing object definition Copy link to section

If value is an object, it has one or more of the following fields:

This example uses the expressive value object to define a route that redirects users with a redirect status of 308 to /end only if the X-Custom-Header header's value is prefixed by valid and ends with value.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "redirects": [\
    {\
      "source": "/start",\
      "destination": "/end",\
      "has": [\
        {\
          "type": "header",\
          "key": "X-Custom-Header",\
          "value": {\
            "pre": "valid",\
            "suf": "value"\
          }\
        }\
      ]\
    }\
  ]
}

Learn more about redirects on Vercel and see limitations.

bulkRedirectsPath Copy link to section

Learn more about bulk redirects on Vercel and see limits and pricing.

Type:string path to a file or folder.

The bulkRedirectsPath property can be used to import many thousands of redirects per project. These redirects do not support wildcard or header matching.

CSV, JSON, and JSONL file formats are supported, and the redirect files can be generated at build time as long as they end up in the location specified by bulkRedirectsPath. This can point to either a single file or a folder containing multiple redirect files.

CSV Copy link to section

CSV headers must match the field names below, can be specific in any order, and optional fields can be ommitted.

redirects.csv

source,destination,permanent
/source/path,/destination/path,true
/source/path-2,https://destination-site.com/destination/path,true
https://old-domain.com/page,/new-page,true

JSON Copy link to section

redirects.json

[\
    {\
        "source": "/source/path",\
        "destination": "/destination/path",\
        "permanent": true\
    },\
    {\
        "source": "/source/path-2",\
        "destination": "https://destination-site.com/destination/path",\
        "permanent": true\
    },\
    {\
        "source": "https://old-domain.com/page",\
        "destination": "/new-page",\
        "permanent": true\
    }\
]

JSONL Copy link to section

redirects.jsonl

{"source": "/source/path", "destination": "/destination/path", "permanent": true}
{"source": "/source/path-2", "destination": "https://destination-site.com/destination/path", "permanent": true}
{"source": "https://old-domain.com/page", "destination": "/new-page", "permanent": true}

You can test bulk redirects locally with vercel dev when you configure bulkRedirectsPath in vercel.json.

Bulk redirect field definition Copy link to section

Field Type Required Description
source string Yes An absolute path or fully qualified URL that matches each incoming request, excluding the query string. The source field does not support query parameters. Vercel ignores any query parameters you include in source. Max 2048 characters.
destination string Yes A location destination defined as an absolute pathname or external URL. Max 2048 characters.
permanent boolean No Toggle between permanent ( 308) and temporary ( 307) redirect. Default: false.
statusCode integer No Specify the exact status code. Can be 301, 302, 303, 307, or 308. Overrides permanent when set, otherwise defers to permanent value or default.
caseSensitive boolean No Toggle whether source path matching is case sensitive. Default: false.
preserveQueryParams boolean No Toggle whether to preserve the query string on the redirect. Default: false.

To improve space efficiency, all boolean values can be the single characters t (true) or f (false) while using the CSV format.

regions Copy link to section

This value overrides the Vercel Function Region in Project Settings.

Type:Array of region identifier String.

Valid values: List of regions, defaults to iad1.

You can define the regions where your Vercel functions are executed. Users on Pro and Enterprise can deploy to multiple regions. Hobby plans can select any single region. To learn more, see Configuring Regions.

Function responses can be cached in the requested regions. Selecting a Vercel Function region does not impact static files, which are deployed to every region by default.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "regions": ["sfo1"]
}

You can also set regions on individual functions using the functions property to override the project-level default. See per-function region configuration for more details.

functionFailoverRegions Copy link to section

Setting failover regions for Vercel functionsare availableon Enterprise plans

Set this property to specify the region to which a Vercel Function should fallback when the default region(s) are unavailable.

Type:Array of region identifier String.

Valid values: List of regions.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "functionFailoverRegions": ["iad1", "sfo1"]
}

You can also set functionFailoverRegions on individual functions using the functions property to override the project-level default. See per-function region configuration for more details.

These regions serve as a fallback to any regions specified in the regions configuration. The region Vercel selects to invoke your function depends on availability and ingress. For instance:

To learn more about automatic failover for Vercel Functions, see Automatic failover. Vercel Functions using the Edge runtime will automatically failover with no configuration required.

Region failover is supported with Secure Compute, see Region Failover to learn more.

Want to talk to our team?

This feature is available on the Enterprise plan.

Schedule Call

rewrites Copy link to section

Type:Array of rewrite Object.

Valid values: a list of rewrite definitions.

If cleanUrls is set to true in your project's vercel.json, do not include the file extension in the source or destination path. For example, /about-our-company.html would be /about-our-company

Rewrites examples Copy link to section

vercel.json

{
    "$schema": "https://openapi.vercel.sh/vercel.json",
    "rewrites": [\
      { "source": "/about", "destination": "/about-our-company.html" }\
    ]
}

vercel.json

{
    "$schema": "https://openapi.vercel.sh/vercel.json",
    "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
}

vercel.json

{
    "$schema": "https://openapi.vercel.sh/vercel.json",
    "rewrites": [\
      { "source": "/resize/:width/:height", "destination": "/api/sharp" }\
    ]
}

vercel.json

{
    "$schema": "https://openapi.vercel.sh/vercel.json",
    "rewrites": [\
      {\
        "source": "/proxy/:match*",\
        "destination": "https://example.com/:match*"\
      }\
    ]
}

vercel.json

{
    "$schema": "https://openapi.vercel.sh/vercel.json",
    "rewrites": [\
      {\
        "source": "/:path((?!uk/).*)",\
        "has": [\
          {\
            "type": "header",\
            "key": "x-vercel-ip-country",\
            "value": "GB"\
          }\
        ],\
        "destination": "/uk/:path*"\
      }\
    ]
}

vercel.json

{
    "$schema": "https://openapi.vercel.sh/vercel.json",
    "rewrites": [\
      {\
        "source": "/dashboard",\
        "missing": [\
          {\
            "type": "cookie",\
            "key": "auth_token"\
          }\
        ],\
        "destination": "/login"\
      }\
    ]
}

Rewrite object definition Copy link to section

Property Description
source A pattern that matches each incoming pathname (excluding querystring).
destination A location destination defined as an absolute pathname or external URL.
permanent A boolean to toggle between permanent and temporary redirect (default true). When true, the status code is 308. When false the status code is 307.
has An optional array of has objects with the type, key and value properties. Used for conditional rewrites based on the presence of specified properties.
missing An optional array of missing objects with the type, key and value properties. Used for conditional rewrites based on the absence of specified properties.

Rewrite has or missing object definition Copy link to section

If value is an object, it has one or more of the following fields:

This example demonstrates using the expressive value object to define a route that rewrites users to /end only if the X-Custom-Header header's value is prefixed by valid and ends with value.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "rewrites": [\
    {\
      "source": "/start",\
      "destination": "/end",\
      "has": [\
        {\
          "type": "header",\
          "key": "X-Custom-Header",\
          "value": {\
            "pre": "valid",\
            "suf": "value"\
          }\
        }\
      ]\
    }\
  ]
}

The source property should NOT be a file because precedence is given to the filesystem prior to rewrites being applied. Instead, you should rename your static file or Vercel Function.

Using has does not yet work locally while usingvercel dev, but does work when deployed.

Learn more about rewrites on Vercel.

routes Copy link to section

The routes property lets you define routing rules using PCRE-compatible regular expressions. You can use routes alongside rewrites, redirects, headers, cleanUrls, and trailingSlash.

For common use cases, use those higher-level properties instead. See Routes vs higher-level properties for guidance on when to use each.

Type:Array of route Object.

Valid values: a list of route definitions.

Route object definition Copy link to section

Property Alias Type Description
src source String A PCRE-compatible regular expression that matches each incoming pathname (excluding querystring).
methods String[] A set of HTTP method types. If you omit this property, the route matches any HTTP method.
dest destination String A destination pathname or full URL, including querystring, with the ability to embed capture groups as $1, $2…
When used with the route's env property, you can also reference environment variables using $VARor${VAR} syntax.
headers Object A set of headers to apply for responses.
status statusCode Number A status code to respond with. Can be used in tandem with Location: header to implement redirects.
continue Boolean If true, routing will continue even when the src is matched.
has Array An array of has objects with the type, key, and value properties. Used for conditional path matching based on the presence of specified properties.
missing Array An array of missing objects with the type, key, and value properties. Used for conditional path matching based on the absence of specified properties.
mitigate Object An object with the property action, which can either be "challenge" or "deny". The specified action performs mitigation on requests that match the route.
transforms Array An array of transform objects. Transform rules let you append, set, or remove request/response headers and query parameters at the edge. See transform examples.
env String[] A whitelist of environment variable names whose values replace $VAR or ${VAR} references in dest values at request time. Only variables listed here are available for expansion. See using environment variables in routes.

The source, destination, and statusCode aliases provide consistency with the rewrites, redirects, and headers properties, which use the same naming conventions.

Vercel processes routes in the order you define them in the array, so wildcard/catch-all patterns should usually be last.

Deprecated route properties Copy link to section

The following route properties are deprecated:

Conditional matching with has and missing Copy link to section

If value is an object, it has one or more of the following fields:

This example uses the value object to define a route that only rewrites to /end if the X-Custom-Header header's value starts with valid and ends with value:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [\
    {\
      "src": "/start",\
      "dest": "/end",\
      "has": [\
        {\
          "type": "header",\
          "key": "X-Custom-Header",\
          "value": {\
            "pre": "valid",\
            "suf": "value"\
          }\
        }\
      ]\
    }\
  ]
}

This example configures custom routes that map to static files and Vercel functions:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [\
    {\
      "src": "/redirect",\
      "status": 308,\
      "headers": { "Location": "https://example.com/" }\
    },\
    {\
      "src": "/custom-page",\
      "headers": { "cache-control": "s-maxage=1000" },\
      "dest": "/index.html"\
    },\
    { "src": "/api", "dest": "/my-api.js" },\
    { "src": "/users", "methods": ["POST"], "dest": "/users-api.js" },\
    { "src": "/users/(?<id>[^/]*)", "dest": "/users-api.js?id=$id" },\
    { "src": "/legacy", "status": 404 },\
    { "src": "/.*", "dest": "https://my-old-site.com" }\
  ]
}

Transform object definition Copy link to section

Property Type Description
type String Must be request.query, request.headers, response.headers, or request.path. This specifies the scope of what your transforms will apply to.
op String These specify the possible operations:
- append appends args to the value of the key, and will set if missing
- set sets the key and value if missing
- delete deletes the key entirely if args is not provided; otherwise, it will delete the value of args from the matching key
The request.path transform only supports set.
target Object An object with key key, which is either a String or an Object. If it is a string, the transform uses it as the header or query key. If it is an object, it may contain one or more of the properties seen below.
Not used for request.path transforms, which operate on the request path as a whole rather than a named key.
args String or String[] or undefined If args is a string or string array, it will be used as the value for the target according to the op property.
The request.path transform requires args to be a single String; an array is rejected.
When env is also set, $VAR and ${VAR} references in args are replaced with environment variable values at request time.
env String[] or undefined A whitelist of environment variable names whose values replace $VAR or ${VAR} references in args at request time. Only variables listed here are available for expansion. A maximum of 64 entries. See using environment variables in transforms.

Transform target object definition Copy link to section

Target is an object with a key property. For the set operation, the transform uses key as the header or query key. For other operations, key acts as a matching condition to determine if the transform should apply.

Property Type Description
key String or Object It may be a string or an object. If it is an object, it must have one or more of the properties defined in the Transform key object definition below.

Transform key object definition Copy link to section

When the key property is an object, it can contain one or more of the following conditional matching properties:

Property Type Description
eq String or Number Check equality on a value
neq String Check inequality on a value
inc String[] Check inclusion in an array of values
ninc String[] Check non-inclusion in an array of values
pre String Check if value starts with a prefix
suf String Check if value ends with a suffix
gt Number Check if value is greater than
gte Number Check if value is greater than or equal to
lt Number Check if value is less than
lte Number Check if value is less than or equal to

Request path transform Copy link to section

The request.path transform overrides the path that the target runtime observes for a request. This is the URL path your Function reads from req.url. It does not change route selection or the destination, and it does not terminate routing. Routing continues after the override, so later routes can still match and rewrite. Adjusting the path and rewriting are separate steps, so you can do both.

Because the path is a single value rather than a named target or key, the only supported op is set, and args must be a single string:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [\
    {\
      "src": "/home",\
      "transforms": [\
        {\
          "type": "request.path",\
          "op": "set",\
          "args": "/new/path"\
        }\
      ]\
    }\
  ]
}

The args value must follow these rules, otherwise the transform is rejected with an error:

You can use the same substitution support as the other transforms in args:

When multiple matching routes set request.path, the transform composes across them and is last-write-wins. A later request.path set overrides an earlier one. The override is included in the CDN cache key, so two requests that differ only by their request.path override are cached as separate entries.

Request path transform in a service Copy link to section

Within a service, a request.path transform in the service's own routes changes the path the service's runtime observes. A top-level rewrite selects which service handles a request, and the service receives the original path. A request.path transform inside the service then rewrites the path its code reads from a request, without changing what was routed.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "services": {
    "my_backend": {
      "root": "backend/",
      "entrypoint": "main:app",
      "routes": [\
        {\
          "src": "/api/(.*)",\
          "transforms": [\
            {\
              "type": "request.path",\
              "op": "set",\
              "args": "/$1"\
            }\
          ]\
        }\
      ]
    }
  },
  "rewrites": [\
    { "source": "/api/(.*)", "destination": { "service": "my_backend" } }\
  ]
}

A public request to /api/users is routed to my_backend, and the service's code observes /users. See Services routing for how the path a service sees relates to route selection.

Transform examples Copy link to section

In this example, you remove the incoming request header x-custom-header from all requests and responses to the /home route:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [\
    {\
      "src": "/home",\
      "transforms": [\
        {\
          "type": "request.headers",\
          "op": "delete",\
          "target": {\
            "key": "x-custom-header"\
          }\
        },\
        {\
          "type": "response.headers",\
          "op": "delete",\
          "target": {\
            "key": "x-custom-header"\
          }\
        }\
      ]\
    }\
  ]
}

In this example, you override the incoming query parameter theme to dark for all requests to the /home route, and set if it doesn't already exist:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [\
    {\
      "src": "/home",\
      "transforms": [\
        {\
          "type": "request.query",\
          "op": "set",\
          "target": {\
            "key": "theme"\
          },\
          "args": "dark"\
        }\
      ]\
    }\
  ]
}

In this example, you append multiple values to the incoming request header x-content-type-options for all requests to the /home route:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [\
    {\
      "src": "/home",\
      "transforms": [\
        {\
          "type": "request.headers",\
          "op": "append",\
          "target": {\
            "key": "x-content-type-options"\
          },\
          "args": ["nosniff", "no-sniff"]\
        }\
      ]\
    }\
  ]
}

In this example, you delete any header that begins with x-react-router- for all requests to the /home route:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [\
    {\
      "src": "/home",\
      "transforms": [\
        {\
          "type": "request.headers",\
          "op": "delete",\
          "target": {\
            "key": {\
              "pre": "x-react-router-"\
            }\
          }\
        }\
      ]\
    }\
  ]
}

In this example, you rewrite the path the runtime observes using a capture group from the matched src. A request to /articles/42 reaches the same destination, but the Function reads /posts/42 from req.url:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [\
    {\
      "src": "/articles/(?<id>[^/]+)",\
      "transforms": [\
        {\
          "type": "request.path",\
          "op": "set",\
          "args": "/posts/$id"\
        }\
      ]\
    }\
  ]
}

Using environment variables in routes Copy link to section

You can reference environment variables in route dest values and transform args using $VAR or ${VAR} syntax. Add the variable names to the env array on the route or transform so they're available for expansion at request time. Values come from your project's environment variables.

If a referenced variable isn't set in your project's environment, the $VAR reference stays as a literal string in the output.

In route destinations Copy link to section

Use the env property on a route to expand environment variables in dest. This example proxies all requests under /api/ to a backend URL stored in the BACKEND_URL environment variable:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [\
    {\
      "src": "/api/(.*)",\
      "dest": "${BACKEND_URL}/api/$1",\
      "env": ["BACKEND_URL"]\
    }\
  ]
}

In transforms Copy link to section

Use the env property on a transform to expand environment variables in args. This example sets a request header x-api-key to the value of the API_KEY environment variable for all requests to the /api route:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [\
    {\
      "src": "/api/(.*)",\
      "transforms": [\
        {\
          "type": "request.headers",\
          "op": "set",\
          "target": {\
            "key": "x-api-key"\
          },\
          "args": "$API_KEY",\
          "env": ["API_KEY"]\
        }\
      ]\
    }\
  ]
}

You can reference multiple environment variables in a single args value. List all referenced variables in the env array:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [\
    {\
      "src": "/proxy/(.*)",\
      "transforms": [\
        {\
          "type": "request.headers",\
          "op": "set",\
          "target": {\
            "key": "authorization"\
          },\
          "args": "Bearer ${AUTH_TOKEN}",\
          "env": ["AUTH_TOKEN"]\
        }\
      ]\
    }\
  ]
}

You can combine transforms with the has and missing properties and the matching conditions in the Transform key object definition.

Routes vs higher-level properties Copy link to section

For common use cases like redirects, rewrites, and custom headers, the higher-level rewrites, redirects, headers, cleanUrls, and trailingSlash properties offer a more concise alternative to routes. You can use both in the same configuration.

The following examples show how common routes patterns map to higher-level properties.

Route parameters Copy link to section

With routes, you use a PCRE-compatible regular expression named group to match the ID and then pass that parameter in the query string. The following example matches a URL like /product/532004 and proxies to /api/product?id=532004:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [{ "src": "/product/(?<id>[^/]+)", "dest": "/api/product?id=$id" }]
}

With rewrites, named parameters pass through in the query string. The following example is equivalent to the routes usage above, but uses rewrites instead:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "rewrites": [{ "source": "/product/:id", "destination": "/api/product" }]
}

Redirects Copy link to section

With routes, you specify the status code to use a 307 Temporary Redirect. Also, this redirect needs to be defined before other routes. The following example redirects all paths in the posts directory to the blog directory, but keeps the path in the new location:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [\
    {\
      "src": "/posts/(.*)",\
      "headers": { "Location": "/blog/$1" },\
      "status": 307\
    }\
  ]
}

With redirects, you disable the permanent property to use a 307 Temporary Redirect. Also, redirects are always processed before rewrites. The following example is equivalent to the routes usage above, but uses redirects instead:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "redirects": [\
    {\
      "source": "/posts/:id",\
      "destination": "/blog/:id",\
      "permanent": false\
    }\
  ]
}

Headers Copy link to section

With routes, you use "continue": true to prevent stopping at the first match. The following example adds Cache-Control headers to the favicon and other static assets:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [\
    {\
      "src": "/favicon.ico",\
      "headers": { "Cache-Control": "public, max-age=3600" },\
      "continue": true\
    },\
    {\
      "src": "/assets/(.*)",\
      "headers": { "Cache-Control": "public, max-age=31556952, immutable" },\
      "continue": true\
    }\
  ]
}

With headers, this is no longer necessary since that is the default behavior. The following example is equivalent to the routes usage above, but uses headers instead:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "headers": [\
    {\
      "source": "/favicon.ico",\
      "headers": [\
        {\
          "key": "Cache-Control",\
          "value": "public, max-age=3600"\
        }\
      ]\
    },\
    {\
      "source": "/assets/(.*)",\
      "headers": [\
        {\
          "key": "Cache-Control",\
          "value": "public, max-age=31556952, immutable"\
        }\
      ]\
    }\
  ]
}

Pattern matching Copy link to section

With routes, you need to escape a dot with two backslashes, otherwise it would match any character PCRE-compatible regular expression. The following example matches the literal atom.xml and proxies to /api/rss to dynamically generate RSS:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [{ "src": "/atom\\.xml", "dest": "/api/rss" }]
}

With rewrites, the . is not a special character so it does not need to be escaped. The following example is equivalent to the routes usage above, but instead uses rewrites:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "rewrites": [{ "source": "/atom.xml", "destination": "/api/rss" }]
}

Negative lookahead Copy link to section

With routes, you use PCRE-compatible regular expression negative lookahead. The following example proxies all requests to the /maintenance page except for /maintenance itself to avoid an infinite loop:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [{ "src": "/(?!maintenance)", "dest": "/maintenance" }]
}

With rewrites, the regex needs to be wrapped in a capture group. The following example is equivalent to the routes usage above, but instead uses rewrites:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "rewrites": [\
    { "source": "/((?!maintenance).*)", "destination": "/maintenance" }\
  ]
}

Case sensitivity Copy link to section

With routes, the src property is case-insensitive, so multiple request paths with different cases serve the same page, creating duplicate content.

With rewrites / redirects / headers, the source property is case-sensitive so you don't accidentally create duplicate content.

trailingSlash Copy link to section

Type: Boolean.

Default Value: undefined.

false Copy link to section

When trailingSlash: false, visiting a path that ends with a forward slash will respond with a 308 status code and redirect to the path without the trailing slash.

For example, the /about/ path will redirect to /about.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "trailingSlash": false
}

true Copy link to section

When trailingSlash: true, visiting a path that does not end with a forward slash will respond with a 308 status code and redirect to the path with a trailing slash.

For example, the /about path will redirect to /about/.

However, paths with a file extension will not redirect to a trailing slash.

For example, the /about/styles.css path will not redirect, but the /about/styles path will redirect to /about/styles/.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "trailingSlash": true
}

undefined Copy link to section

When trailingSlash: undefined, visiting a path with or without a trailing slash will not redirect.

For example, both /about and /about/ will serve the same content without redirecting.

This is not recommended because it could lead to search engines indexing two different pages with duplicate content.

public Copy link to section

The public property is no longer supported and will cause deployment failures. Remove it from your vercel.json immediately to fix broken deployments.

Remove the "public" key from your vercel.json:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json"
}

Deployments always keep source view and logs view protected behind authentication. The public property had no effect and is no longer accepted by the validator.

Legacy Copy link to section

Legacy properties are still supported for backwards compatibility, but are deprecated.

name Copy link to section

The name property has been deprecated in favor of Project Linking, which allows you to link a Vercel project to your local codebase when you run vercel.

Type: String.

Valid values: string name for the deployment.

Limits:

The prefix for all new deployment instances. Vercel CLI usually generates this field automatically based on the name of the directory. But if you'd like to define it explicitly, this is the way to go.

The defined name is also used to organize the deployment into a project.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "name": "example-app"
}

version Copy link to section

The version property should not be used anymore.

Type: Number.

Valid values: 1, 2.

Specifies the Vercel Platform version the deployment should use.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "version": 2
}

alias Copy link to section

The alias property should not be used anymore. To assign a custom Domain to your project, please define it in the Project Settings instead. Once your domains are, they will take precedence over the configuration property.

Type: Array or String.

Valid values: domain names (optionally including subdomains) added to the account, or a string for a suffixed URL using .vercel.app or a Custom Deployment Suffix ( available on the Enterprise plan).

Limit: A maximum of 64 aliases in the array.

The alias or aliases are applied automatically using Vercel for GitHub, Vercel for GitLab, or Vercel for Bitbucket when merging or pushing to the Production Branch.

You can deploy to the defined aliases using Vercel CLI by setting the production deployment environment target.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "alias": ["my-domain.com", "my-alias"]
}

scope Copy link to section

The scope property has been deprecated in favor of Project Linking, which allows you to link a Vercel project to your local codebase when you run vercel.

Type: String.

Valid values: For teams, either an ID or slug. For users, either a email address, username, or ID.

This property determines the scope ( Hobby team or team) under which the project will be deployed by Vercel CLI.

It also affects any other actions that the user takes within the directory that contains this configuration (e.g. listing environment variables using vercel secrets ls).

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "scope": "my-team"
}

Deployments made through Git will ignore the scope property because the repository is already connected to project.

env Copy link to section

We recommend against using this property. To add custom environment variables to your project define them in the Project Settings.

Type:Object of String keys and values.

Valid values: environment keys and values.

Environment variables passed to the invoked Vercel functions.

This example will pass the MY_KEY static env to all Vercel functions and the SECRET resolved from the my-secret-name secret dynamically.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "env": {
    "MY_KEY": "this is the value",
    "SECRET": "@my-secret-name"
  }
}

build.env Copy link to section

Type:Object of String keys and values inside the build``Object.

Valid values: environment keys and values.

Environment variables passed to the Build processes.

The following example will pass the MY_KEY environment variable to all Builds and the SECRET resolved from the my-secret-name secret dynamically.

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "env": {
    "MY_KEY": "this is the value",
    "SECRET": "@my-secret-name"
  }
}

builds Copy link to section

We recommend against using this property. To customize Vercel functions, please use the functions property instead. If you'd like to deploy a monorepo, see the Monorepo docs.

Type:Array of build Object.

Valid values: a list of build descriptions whose src references valid source files.

Build object definition Copy link to section

The following will include all HTML files as-is (to be served statically), and build all Python files and JS files into Vercel functions:

vercel.json

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "builds": [\
    { "src": "*.html", "use": "@vercel/static" },\
    { "src": "*.py", "use": "@vercel/python" },\
    { "src": "*.js", "use": "@vercel/node" }\
  ]
}

When at least one builds item is specified, only the outputs of the build processes will be included in the resulting deployment as a security precaution. This is why we need to allowlist static files explicitly with @vercel/static.

Last updated August 14, 2026

Related Vercel documentation

Cross-link map: Static Configuration with vercel.json (/docs/project-configuration/vercel-json)

From the Vercel docs graph (built 2026-09-25T05:54:54.356Z), spanning vercel.com docs + KB, nextjs.org, ai-sdk.dev, and other Vercel documentation sites. Full graph as JSON: https://vercel.com/docs/graph.json

Semantically closest pages

Prerequisites

This page links to (46)

Pages that link here (57)

By site: vercel-changelog (1) · vercel-kb (12) · vercel-docs (44)

From vercel-changelog

From vercel-kb

From vercel-docs


Previous\ \ Project Configuration

Next\ \ vercel.toml

Was this helpful?

supported.

Send