File System API (v2)

The File System API allows you to interact with the file system in a Node.js environment.
Table of Contents
Deprecated:

This version (v2) of the File System API is deprecated. It should not be used for new projects.


If you have issues or concerns with File System API (v1 or v2), see our File System API (v1/v2) Feedback discussion.

Node.js Support:

This version (v2) of the File System API will only work with Node.js <= 14.x.

A reference of the .output directory consumed by Vercel's Build Step with every Deployment, which is expected to contain your app's compiled code and instructions for how to serve it to visitors.

Whenever a new Deployment is created on Vercel, its source files will be retrieved from their origin location (a Git repository, for example) and processed within the Build Step, after which they are made available on the Edge Network.

Inside of this Build Step, the vercel build command provided by Vercel CLI is automatically invoked, which will retrieve the Project Settings and invoke the Build Command specified for the Project. This will make the respective Framework transform the source code and prepare it for delivery.

Afterwards, vercel build will handle features natively provided by Vercel (such as Node.js Serverless Functions in the api directory or _middleware.js) and produce several files that it combines with the files produced by the Project's Build Command.

The outcome of this process is a .output directory that is passed on to the File System API at the end of the Build Step, containing instructions of which files to deliver to visitors and their respective configuration manifests.

Most commonly, the File System API is not something you need to worry about.

Frameworks that support Vercel without any additional configuration (like Next.js, Nuxt, or SvelteKit) are automatically producing a .output directory that instructs the platform how to behave. They pass on all of the resources created within your source code (such as Pages or API Routes).

If you are a framework author looking to integrate with Vercel, you can use this reference as a way to understand which files you would want to create within the .output directory, for the platform to understand them.

Additionally, if you are not using a framework and would like to still take advantage of any of the features that those frameworks provide, you can create the directory yourself, using a custom command-line interface or by including it in your source files.

Relevant Directories:


.output/server/pages
.output/server/pages/api
.output/static

If you'd like to expose resources to your visitors once the Deployment has finished, it is required to place them inside one of the directories mentioned below. Files outside of these directories are ignored and will not be served to visitors.

Directory: .output/server/pages

Regardless of whether the Pages you'd like to serve to your visitors are generated on-demand (whenever a request arrives) or statically generated ahead of time, including them as part of your Deployment can be done by creating a single file for every page, and Vercel will handle the rest for you.

More specifically, you can place the source of Pages that you have statically generated ahead of time in the form of HTML files in the directory shown above and they will automatically be served at the root of the URL of your Deployment.

The same is the case for Pages that you would like to generate on-demand using Server-Side Rendering: Place a Serverless Function in the directory and it will be invoked whenever a request arrives for the path defined in its file name.

In favor of performance, it is recommended to statically generate Pages ahead of time as much as possible. If the need for dynamism arises, feel free to switch to Page Functions and ideally even enable Pre-Rendering, to retain as much performance as possible.

All files within the pages directory are considered files that should be mounted to the URL of the Deployment. If your Functions depend on other files, they have to be included through the Bundling Configuration and placed outside of pages (in a different arbitrary directory at the root of .output, for example).

It is recommended to leave the bundling of files to Vercel if a file is used by multiple Functions. If a file is only used by a single Function, you may combine those files into a single Function based on your own choosing.

The extensions of the files within the pages directory are automatically stripped before the Pages are made available in the URL of the Deployment, under the same name that was used for the file. This happens regardless of which extension was used.

If files are placed in sub directories within pages, those will become part of the URL too, and be included before the page name.

By default, only files with the extensions .html (statically generated ahead of time) and .js (Node.js Function, so generated on-demand with every incoming request) may be placed inside of the pages directory.

If you would like to provide Page Functions that use a different runtime than Node.js, you can do so using the Function Configuration, which also includes other options.

If you were to add file named about.html inside of the pages directory, it will be served at /about in the URLs assigned to your Deployment.

Respectively, if you were to place a file named blog.js inside of the directory, it will be served at /blog and the Function contained inside of the file will be invoked whenever a request arrives for that URL path.

Placing a file in test/about.html would mount it to /test/about in the URL.

This is what the directory could look like in a real scenario (you can learn more about the purpose of the .nft.json file in Exposed Files above):

Directory: .output/static

If you would like to provide static files that should be served without any transformation as part of your Deployment, you can do so by including them in this directory.

The files will be made available at the root (/) of the Deployment's URL and neither their contents, nor their file name or extension will be mutated in any way. Sub directories within static are also retained in the URL, and are appended before the file name.

If a Page or API Route with the same name in the final URL exists, they will be overwritten by the Static File and therefore won't be accessible through the URL anymore.

It is therefore recommended to use this directory for files that are not directly accessed by visitors, but instead loaded on Pages (like client-side JavaScript bundles) or accessed by machines (like robots.txt). Files that are directly accessed by visitors are considered Pages and shouldn't be placed here.

Since all of the files in this directory are exposed as part of the Deployment's URL, you also shouldn't use it for files that your Page or API Route Functions might depend on for execution. Those can be included through Bundling Configuration instead.

This is what the directory could look like in a real scenario:

Directory: .output/server/pages/api

If one of your Pages relies on data that should be delivered from, or to the client-side (the browser), you can use this directory to include API Routes as part of your Deployment that will send and accept this data.

They can also be helpful in scenarios where third-parties or other types of clients (like native mobile apps) wish to access this data, or any other types of actions that have to be performed that were triggered by a visitor.

API Routes are designed to be accessed by Pages or machines, but not by humans. If you'd like to display something to visitors, create a Page instead.

Under the hood, like on-demand Pages, API Routes are powered by Serverless Functions.

When it comes to the files in the directory that are exposed in the Deployment's URL and custom runtimes, API Routes behave like Pages. Otherwise, they are completely separate concepts and should be separated distinctively.

This is what the directory could look like in a real scenario:

  • Directory: .output/server/pages

    Generating Pages on-demand using Serverless Functions bears a significant performance drawback, because their HTML markup has to be generated again for every incoming request, which is slower than delivering HTML that was statically generated ahead of time.

    Even if your Page returns the Cache-Control header and its responses are cached on Vercel's Edge Network, the first request per region would still be slow, which means that the first visitor in a certain region would see a slower response.

    Thankfully, however, Vercel offers two different types of Functions: Serverless Functions and Edge Functions. The former are the traditional kind powered by Lambdas, whereas the latter runs directly on the Edge Network and can respond much quicker.

    You can place Middleware in .output/server/pages, and it sits between the client (the browser), and a Page or API Route. This means you can statically generate those ahead of time or cache their responses on the Edge Network, while still executing code on every request.

    Because Middleware has almost no noticeable impact on performance, it is run on every request and can perform lightweight operations such as forwarding visitors to a different URL, resolving to a different URL, or performing any sort of validation.

    Unlike all other Resources, Middleware requires Function Configuration to work, as it determines the URL paths that the Middleware should be responsible for. For the other Resources, this is inferred based on the location and name of the files.

    Middleware files are never directly exposed as part of the Deployment's URL. Instead, based on their configuration, they are made available on existing URL paths that resolve to Pages or API Routes, which is the part that makes them the "middle-ware".

    Currently, only JavaScript (invoked by V8) is supported as a runtime for Middleware.

    This is what the directory could look like in a real scenario:

    For the above example, you could place the following in functions-manifest.json:

    {
      "version": 1,
      "pages": {
        "_middleware.js": {
          "runtime": "web",
          "env": [],
          "files": ["server/pages/_middleware.js"],
          "name": "pages/_middleware",
          "page": "/",
          "regexp": "^/.*$",
          "sortingIndex": 1
        }
      }
    }

    Additionally, this is what you could place in _middleware.js:

    const getResult = (body, options) => ({
      promise: Promise.resolve(),
      waitUntil: Promise.resolve(),
      response: new Response(body, options),
    });
     
    _ENTRIES = typeof _ENTRIES === 'undefined' ? {} : _ENTRIES;
     
    _ENTRIES['middleware_pages/_middleware'] = {
      default: async function ({ request }) {
        // Body
        if (request.url.endsWith('/middleware-body')) {
          return getResult('hi from the edge', {});
        }
     
        // Rewrite
        if (request.url.endsWith('/middleware-rewrite')) {
          return getResult(null, {
            headers: {
              'x-middleware-rewrite': '/blog',
            },
          });
        }
     
        // Redirect
        if (request.url.endsWith('/middleware-redirect')) {
          return getResult(null, {
            status: 308,
            headers: {
              Location: '/blog',
              'x-middleware-redirect': '/blog',
            },
          });
        }
     
        // Don't do anything
        return getResult(null, {
          headers: {
            'x-middleware-next': '1',
          },
        });
      },
    };

    File Names:


    .output/routes-manifest.json
    .output/functions-manifest.json
    .output/server/pages/**/[function].nft.json
    .output/images-manifest.json
    .output/prerender-manifest.json
    .output/build-manifest.json

    If you would like to customize the behavior of any of the Resources you have provided with your Deployment, or control Vercel's behavior in general, you can provide several optional configuration files within the .output directory.

    File Name: .output/routes-manifest.json

    If you'd like to point certain URL paths to others on your Deployment or attach headers to some of them, you can do so using this configuration file.

    You can forward visitors to different URLs (if you've changed the URL of a blog post, for example), change the URL that is displayed for them (if you'd like multiple URLs to resolve to a single one, for example), or customize the behavior of the client that sent the request through headers.

    The following configuration properties are allowed within the configuration file:

    KeyTypeRequiredDescription
    versionIntegerYesThe version of the configuration that should be used. The most recent one for this file is currently 3.
    basePathStringYesA path that is prepended to all Routes and Routes. For example, you might want to mount your entire application to /something.
    pages404BooleanYesWhether or not a Page named 404 (can be HTML or a Function) should be served if a path isn't found for an incoming request.
    redirectsListNoA list of Maps for forwarding requests from one URL path to another, whose properties are described below.
    headersListNoA list of Maps for returning headers for certain URL paths, whose properties are described below.
    rewritesListNoA list of Maps for ensuring that certain URL paths resolve to other URLs, whose properties are described below.
    dynamicRoutesListNoA list of Maps that describe Pages or API Routes that include path segments (like blog/[slug]) and therefore result in rewrites, whose properties are described below.

    Within redirects, every Map can contain the following properties:

    KeyTypeRequiredDescription
    sourceStringYesThe URL path on which the redirect will be made available.
    destinationStringYesThe URL path to which the visitor should be redirected.
    statusCodeIntegerYesThe HTTP status code that should be returned as part of the response for redirecting the visitor. Possible values are either 301, 302, 307, or 308. The last two are recommended, while the first two should ideally only be used for backwards-compatibility with legacy clients (e.g. browsers).
    regexStringYesA regular expression describing the URL path on which the redirect should be served. While source is only a String representation of the path, regex is the value that is used for actually validating whether the redirect should apply to an incoming request, or not.

    Within headers, every Map can contain the following properties:

    KeyTypeRequiredDescription
    sourceStringYesThe URL path on which the headers will be made available.
    headersListYesA list of Maps containing headers that should be returned from URL paths that match regex, where key is a String containing the name of the header, and value is a String containing its respective value.
    regexStringYesA regular expression describing the URL path on which the headers should be served. While source is only a String representation of the path, regex is the value that is used for actually validating whether the headers should apply to an incoming request, or not.

    Within rewrites, every Map can contain the following properties:

    KeyTypeRequiredDescription
    sourceStringYesThe URL path on which the rewrite will be made available.
    hasIntegerNoA list of Maps containing rules that the incoming request has to match before the rewrite applies. Within them, type is an Enum with header, cookie, host or query as the value, key is a String containing the respective key that should be asserted, and value is the same, but for the value that should be asserted.
    destinationStringYesThe URL path that should be served to the visitor when a URL path that matches regex is accessed.
    regexStringYesA regular expression describing the URL path on which the rewrite should be served. While source is only a String representation of the path, regex is the value that is used for actually validating whether the rewrite should apply to an incoming request, or not.

    Within dynamicRoutes, every Map can contain the following properties:

    KeyTypeRequiredDescription
    pageStringYesThe name (in the same format as used in Function Configuration) of the Page or API Route that should receive the incoming request if its URL matches the pattern provided in regex.
    regexStringYesA regular expression describing the URL path on which the Page or API Route should be served.
    routeKeysMapNoQuery string parameters that should be passed to the destination Page or API Route, where every key is the segment in namedRegex that should be captured and every value is the name of the query string parameter that should receive its value.
    namedRegexStringNoA regular expression describing the URL path on which the Page or API Route should be served. The difference to regex is that this property can contain path segments (like <post>) that will automatically be transformed into query string parameters using routeKeys.

    This is what the configuration file could look like in a real scenario:

    {
      "version": 3,
      "basePath": "",
      "pages404": true,
      "redirects": [
        {
          "source": "/nice/",
          "destination": "/stuff",
          "statusCode": 308,
          "regex": "^/nice.*$"
        }
      ],
      "headers": [
        {
          "source": "/",
          "headers": [
            {
              "key": "x-custom-header",
              "value": "my custom header value"
            }
          ],
          "regex": "^.*$"
        }
      ],
      "rewrites": [
        {
          "source": "/admin",
          "has": [
            {
              "type": "cookie",
              "key": "authorized",
              "value": "true"
            }
          ],
          "destination": "/secret",
          "regex": "^/admin.*$"
        }
      ],
      "dynamicRoutes": [
        {
          "page": "/blog/[post]",
          "regex": "^/blog/([^/]+?)(?:/)?$",
          "routeKeys": {
            "post": "post"
          },
          "namedRegex": "^/blog/(?<post>[^/]+?)(?:/)?$"
        }
      ]
    }

    File Name: .output/functions-manifest.json

    If you have provided on-demand Pages or API Routes as part of your Deployment, you might find yourself needing to customize their behavior on Vercel.

    With this configuration file, you can customize the memory size of their underlying Functions, which region on the Edge Network they are deployed to, and how long they should be able to run.

    Additionally, it allows for customizing which runtime should be used for those Functions in cases where you would like to run your code in a non-Node.js Environment. This means that on-demand Pages and API Routes can be written in any language.

    Before configuring the Functions created in your Deployment, it is recommended to first learn about the conceptual models for Serverless Functions and Edge Functions (depending on which ones you'd like to use), as it will help you make the right decisions while customizing their default behavior along the way.

    The following configuration properties are allowed within the configuration file:

    KeyTypeRequiredDescription
    versionIntegerYesThe version of the configuration that should be used. The most recent one for this file is currently 1.
    pagesMapYesA map of on-demand Pages (Functions), API Routes or Middlewares and the respective configuration properties for each one. The keys are Strings containing the names of the Functions, without their extensions. The values are Maps, whose properties are described below.

    Within pages, every key can have the following Map as its value:

    KeyTypeRequiredDescription
    memoryIntegerNoHow much memory (in MB) should be made available to the Function. Only Integers between 128 and 3009 are allowed. The CPU configuration will scale linearly in proportion to the memory configuration (at 1769 MB memory, for example, a Function has the equivalent of one full vCPU).
    maxDurationIntegerNoHow long the Function should be allowed to run for every request in seconds. Only Integers between 1 and the Serverless Function Execution Timeout limit of your plan are allowed. It is recommended to use a small value, as larger values will keep visitors waiting for longer.
    regionsEnumNoThe regions on our Edge Network that the Function should be deployed to. It is recommended to keep your Functions close to your visitors, but also close to your data source, to keep latency for both at a minimum.
    runtimeEnumNoThe identifier of the Lambda runtime that you'd like to use for your Function. Defaults to the Node.js Version configured in the Project Settings. If this property is used, handler is required alongside it. It can also be web if you'd like to deploy an Edge Function (does not require handler).
    handlerStringNoThe name of the file that should be invoked by the Lambda runtime defined above whenever a request arrives.

    Additionally, the Map mentioned above should contain the following properties if runtime is web and the respective Function is used as Middleware (if it's not used as Middleware and runtime is still web, the properties are optional):

    KeyTypeRequiredDescription
    envListYesA list of Strings that represent the names of Environment Variables that should be retrieved from the Project Settings and made available to the code at execution time with their values.
    filesListYesA list of Strings that represent source files that are relevant for the Middleware. It has to contain at least one item that matches the name property. Any additional entry will be concatenated (learn more about Edge Function Bundling) together with the contents of the file present at this path. All paths have to begin with server/.
    nameStringYesThe path of the respective Middleware file that the configuration Map is responsible for. It is required to begin with pages/ and end in _middleware.
    pageStringYesThe path in the URL for which the respective Middleware file is responsible. If it's responsible for multiple sub paths, you don't need to consider those here – only their parent path.
    regexpStringYesA regular expression describing the URL path for which the respective Middleware file is responsible. This value is considered every time a request arrives, to determine whether to execute the Middleware, or not.
    sortingIndexIntegerYesIf multiple Middlewares were defined for the same path, this value defines in which order they should be executed.

    This is what the configuration file could look like in a real scenario:

    {
      "version": 1,
      "pages": {
        "my-page.js": {
          "memory": 128,
          "maxDuration": 3,
          "regions": ["hkg1"]
        },
        "api/date.go": {
          "runtime": "go1.x",
          "handler": "my-go-api.bin"
        },
        "api/hello.js": {
          "runtime": "web"
        },
        "_middleware.js": {
          "runtime": "web",
          "env": [],
          "files": ["server/pages/_middleware.js"],
          "name": "pages/_middleware",
          "page": "/",
          "regexp": "^/.*$",
          "sortingIndex": 1
        }
      }
    }

    File Name: .output/server/pages/**/[function].nft.json

    If you are expecting scenarios in which multiple Pages or API Routes are making use of the same code for their Functions (which might apply for utility files), you can inform Vercel about those files, so that it can automatically determine the most efficient way to make the files available where needed.

    Instead of having to ensure that every Page and API Route Function includes all of the code it requires for being able to run, you can inform the platform which Functions depend on which files, instead of copying code into multiple places (which increases disk usage in the final Function). Vercel can then automatically figure out the most efficient placement for these files.

    The configuration file can be placed alongside Pages and API Routes on any level within pages, and [path] in the configuration file name (see the "File Name" example above) has to match them. The dependency files of your Functions can be placed inside of the .output/inputs directory.

    In the case that the runtime property of a Function is set to web using Function Configuration, it is considered an Edge Function and will not be able to make use of the .nft.json configuration standard for bundling files.

    Instead, the files property in the respective Function Configuration entry can be used to inform the platform which files the Edge Function might depend on, so that multiple Edge Functions can make use of the same shared source code files, if needed.

    As mentioned in Function Configuration, the first entry of files is required to be the Edge Function's entrypoint file, but all other items in the List will have their file contents appended to the entrypoint file.

    Note that the _ENTRIES property within the entrypoint file will not receive additional properties. Instead, the entrypoint file and the other files are joined together as strings and create a new entrypoint file.

    If multiple Edge Functions are making use of the same source code, use this property to help Vercel understand which Edge Function depends on which files, so that it can apply smart and efficient bundling, just like for Serverless Functions.

    The following configuration properties are allowed within the configuration file:

    KeyTypeRequiredDescription
    versionIntegerYesThe version of the configuration that should be used. The most recent one for this file is currently 1.
    filesListYesA list of Strings representing the paths that a Page and API Route Function might depend on, relative to their location. If a list of Maps is used instead, this is reflected in their input properties, and their output properties would be the paths within the final Lambda to which the files should be mounted (relative to the root). Only use Maps if necessary.

    If a Page were to be located at pages/about.js, its respective configuration file for bundling would be located at pages/about.nft.json.

    If your application contains dependencies within a node_modules directory which multiple Functions need to access, you don't need to copy those dependencies into multiple places. Instead, Vercel will automatically bundle the files in a smart way, so that disk usage of the final Functions is kept to a minimum.

    This is what the configuration file could look like in a real scenario:

    {
      "version": 1,
      "files": [
        {
          "input": "../../../data.txt",
          "output": "my-folder/data.txt"
        }
      ]
    }

    File Name: .output/images-manifest.json

    If you would like to provide images as part of your Deployment ahead of time, you can include them as Static Files. Those images will be made available without modifications on your Deployment's URL, so you can load them from anywhere (like your frontend).

    For optimal performance, however, it is recommended to load your images through Vercel's native Image Optimization endpoint, which automatically adjusts the size and quality of your images, to make sure they are served to your visitors as quickly as possible.

    The endpoint is available at the /_vercel/image path of the respective Deployment and accepts the following query string parameters:

    KeyTypeRequiredDescription
    urlStringYesThe URL of the image that should be optimized (like /static/image.png). If it's an external URL, its domain must be included as part of domains in the configuration file.
    wIntegerYesThe width that the image should be resized to (like 200). Only the Integer passed through sizes in the images configuration property are allowed as the value.
    qIntegerNoThe quality level that the image should be reduced to (like 70). Any Integer between 100 (maximum quality) and 1 (lowest quality) is allowed as the value.

    The following configuration properties are allowed within the configuration file:

    KeyTypeRequiredDescription
    versionIntegerYesThe version of the configuration that should be used. The most recent one for this file is currently 1.
    imagesMapYesA map of configuration properties (described below) that are considered every time an image is optimized.

    Within images, the following Map has to be replaced:

    KeyTypeRequiredDescription
    sizesListYesA list of Integers containing the allowed widths for when images are resized.
    domainsListYesA list of Strings containing the domains to be allowed as part of the URL when optimizing images.
    minimumCacheTTLIntegerNoThe amount of time (in seconds) that should pass before an image is marked as stale. If an image is marked as stale, the next time a new request for it comes in, it will asynchronously be optimized again in the background.
    formatsListNoA list of Strings that represent potential values of the Accept header of an incoming request (defaults to image/webp, but allows image/avif as an additional entry). If an incoming request has a matching Accept header, the image will be transformed into this format. If no matching header is found, the image's original format remains unchanged.

    This is what the configuration file could look like in a real scenario:

    {
      "version": 1,
      "images": {
        "sizes": [256, 384],
        "domains": ["external-site.com"],
        "minimumCacheTTL": 60,
        "formats": ["image/avif", "image/webp"]
      }
    }

    File Name: .output/prerender-manifest.json

    When providing Pages for your Deployment, you can choose between statically generating them ahead of time (and supplying Vercel with HTML files), or generating them on-demand, every time a request comes in.

    It is generally recommended to opt for providing HTML files to the platform. This provides significant performance advantages because the Pages don't have to be rendered on-demand.

    If you are dealing with a large amount of Pages, statically generating them all ahead of time can be slow. To solve this, you can provide Pre-Rendering configuration, which allows you to generate some of the Pages (for example, the ones that are commonly visited) ahead of time, while automatically generating the rest on-demand.

    Furthermore, it allows you to easily keep statically generated Pages up-to-date, without having to deploy every update again.

    Incremental Static Regeneration is a pre-rendering technique that enables you to update statically-generated pages on an interval, and generate missing pages on-demand. See our ISR docs to learn more.

    Draft Mode allows you to set specific pages to bypass ISR caching and render at request time. This is useful for viewing draft content from a headless CMS without manually triggering page revalidation or waiting for the revalidation interval to pass.

    The following configuration properties are allowed within the configuration file:

    KeyTypeRequiredDescription
    versionIntegerYesThe version of the configuration that should be used. The most recent one for this file is currently 3.
    routesMapYesA map of statically generated Pages (HTML files) that should be kept up-to-date and configuration properties for each one. The keys are Strings containing the names of the HTML files, without their extensions. The values are Maps, whose properties are described below.
    dynamicRoutesMapYesA map of on-demand Pages (Functions) that should be used for statically generating missing Pages and configuration properties for each one. The keys are Strings containing the names of the Functions, without their extensions. The values are Maps, whose properties are described below.
    previewMapYesA map containing a single property named previewModeId, which is either null or a String containing any arbitrary characters. In the latter case, passing a cookie named __prerender_bypass with this value will bypass the ISR caches and force the Pages to be generated fresh on-demand.

    Used for associating statically generated Pages (HTML) with on-demand Pages (Functions). The statically generated Pages can be served to visitors, and their respective on-demand Page match is used for updating the HTML asynchronously in the background.

    This means visitors never receive a slow response, and the HTML is kept up-to-date.

    Within routes, every key can have the following Map as its value:

    KeyTypeRequiredDescription
    initialRevalidateSecondsIntegerYesThe amount of seconds that a Page is allowed to be delivered before the Function for updating its contents is invoked in the background.
    srcRouteStringYesThe name of a on-demand Page (Function) without its extension, which is used for updating the HTML of the statically generated Page.
    dataRouteStringYesThe name of a on-demand Page (Function) without its extension, which is used for updating the JSON of the statically generated Page. Can be used for client-side transitions, but can also be left as an empty String if not needed.

    Can be used in combination with routes, but also standalone.

    Its purpose is to capture URL path segments and point them to on-demand Pages (Functions), which will then produce statically generated Pages (HTML) for the respective path. Before the on-demand Pages are invoked, you can also make the platform first consider Pages that were already generated ahead of time (HTML) through fallback, which is recommended for optimal performance.

    Overall, this means that incoming requests would first result in the platform trying to find a matching Page that was statically generated ahead of time, after which the respective on-demand Page (Function) is invoked if no match was found.

    Within dynamicRoutes, every key can have the following Map as its value:

    KeyTypeRequiredDescription
    routeRegexIntegerYesA regular expression describing the URL path under which a Page with Incremental Static Regeneration should be attached.
    fallbacknull or StringYesDescribes whether the route captured above is only used for statically generating new Pages on-demand if they're missing (null), or if the platform should first consider Pages that were statically generated ahead of time before generating new ones (String referencing the Page without the HTML extension).
    dataRouteStringYesThe same as the dataRoute property for routes, but for updating the JSON of the Page that was statically generated on-demand.
    dataRouteRegexStringYesA regular expression describing the URL path under which the JSON for the dataRoute property above should be served.

    This is what the configuration file could look like in a real scenario:

    {
      "version": 3,
      "routes": {
        "/my-isr-page": {
          "initialRevalidateSeconds": 30,
          "srcRoute": "/my-isr-page",
          "dataRoute": ""
        }
      },
      "dynamicRoutes": {
        "/my-isr-page": {
          "routeRegex": "^/my-isr-page$",
          "dataRoute": "",
          "fallback": null,
          "dataRouteRegex": ""
        }
      },
      "preview": {
        "previewModeId": null
      }
    }

    File Name: .output/build-manifest.json

    If you'd like to configure the behavior of your Deployment's Build Step, you can do so by providing the file mentioned above.

    The following configuration properties are allowed within the configuration file:

    KeyTypeRequiredDescription
    versionIntegerYesThe version of the configuration that should be used. The most recent one for this file is currently 1.
    cacheListNoA list of Strings containing globs, where each one represents paths that should be cached.

    This is what the configuration file could look like in a real scenario:

    {
      "version": 1,
      "cache": ["build/**/*"]
    }

    You can add support for framework detection and define default values on Vercel by adding it to the @vercel/frameworks package:

    1. Fork the vercel/vercel repository on GitHub.
    2. Add your framework to the @vercel/frameworks package by editing the file ./packages/frameworks/src/frameworks.ts.
    3. Copy the structure of an existing framework and adjust the fields for the new framework.
    4. You can add default routes that will always be applied to Projects that use this framework or specify some paths that will be cached to speed up the build process (note that this step can be ignored if the framework makes use of the file system API).
    5. The settings property either contains a value or a placeholder. If the setting should allow the user to override it, use placeholder. To prevent the user from overriding, use value. For example, the Output Directory for Hugo is public by default, but can be changed through its config file, so we use placeholder with an explanation of what can be used.
    6. Add a template to the examples directory: The name of the directory should match the slug of the framework used in @vercel/frameworks. The /.github/EXAMPLE_README_TEMPLATE.md file is a template for creating a README.md file for the template.
    7. Create a Pull Request! After your Pull Request has been merged, someone from Vercel will enable the framework in the API so that anyone can select the framework on the Vercel dashboard and deploy it.
    Last updated on August 26, 2024