Use the File System Route API when you want to programmatically create pages from your GraphQL data, e.g. to create individual blog post pages for your blog. With this API you can control the file path and queried data by adding some extra notation to the names of your files without touching or creating gatsby-node.js whatsoever.

This page documents the APIs and conventions for using the file system as the primary way of creating pages. You should be able to accomplish most common tasks with this file-based API. If you want more control over the page creation you should use the createPages API.

In short, these APIs enable you to programmatically create pages from Gatsby’s GraphQL data layer and to create client-only routes.

A complete example showcasing all options can be found in Gatsby’s “examples” folder.

Collection routes

Imagine a Gatsby project that sources a product.yaml file and multiple Markdown blog posts. At build time, Gatsby will automatically infer the fields and create multiple nodes for both types (Product and MarkdownRemark). There are two ways you could query for that data:

  • You can perform GraphQL queries like allProduct or allMarkdownRemark from inside a component, as usual.
  • You can use the File System Route API to access node information directly from the file path.

To use the File System Route API, use curly braces ({ }) in your filenames to signify dynamic URL segments that relate to a field within the node. Here are a few examples:

  • src/pages/products/{}.js will generate a route like /products/burger
  • src/pages/products/{Product.fields__sku}.js will generate a route like /products/001923
  • src/pages/blog/{MarkdownRemark.parent__(File)__name}.js will generate a route like /blog/learning-gatsby

At build time, Gatsby uses the content within the curly braces to generate GraphQL queries to retrieve the nodes that should be built for a given collection (collection here refers to all nodes of a given type, e.g. all Markdown files for MarkdownRemark). Gatsby then runs those queries to grab all the nodes and create a page for each of them. Gatsby also adds an id field to every query automatically, to simplify integration with page queries.

Syntax (collection routes)

There are some general syntax requirements when using collection routes:

  • Filenames must start and end with curly braces ({ }).
  • Types can be both lowercase and uppercase (e.g. MarkdownRemark or contentfulMyContentType).
  • The initial type name must be followed by a period (.).

Note: To keep things consistent, only capitalized type names are used in the examples.

In addition to files, you can also name folders with this syntax. This allows you to create nested routes. For example:

  • src/pages/products/{}/{Product.color}.js will generate a route like /products/fidget-spinner/red
  • src/pages/products/{}/template.js will generate a route like /products/fidget-spinner/template

Dot notation

Using . you signify that you want to access a field on a node of a type.

src/pages/products/{}.js generates the following query:

Underscore notation

Using __ (double underscore) you signify that you want to access a nested field on a node.

src/pages/products/{Product.fields__sku}.js generates the following query:

You can nest as deep as necessary, e.g. src/pages/products/{Product.fields__date__createdAt}.js generates the following query:

Parentheses notation

Using ( ) you signify that you want to access a GraphQL union type. This is often possible with types that Gatsby creates for you. For example, MarkdownRemark always has File as a parent type, and thus you can also access fields from the File node. You can use this multiple levels deep, too, e.g. src/pages/blog/{Post.parent__(MarkdownRemark)__parent__(File)__name}.js.

src/pages/blog/{MarkdownRemark.parent__(File)__name}.js generates the following query:

Component implementation

Naming your file with the File System Route API will generate routes for each node and will automatically pass the field name via props.params to the React component and as a variable to the GraphQL query. As explained in Querying data in pages with GraphQL you can render data from a node on the page by filtering only for the given id or field name.

For example, in the component itself (e.g. src/pages/products/{}.js) you’re able to access the name via props.params and as a variable in the GraphQL query (as $name). However, we recommend filtering by id as this is the fastest way to filter.

If you need to customize the query used for collecting the nodes (e.g. filtering out any product of type "Food"), you should use the createPages API instead as File System Route API doesn’t support this at the moment.

Routing and linking

Gatsby “slugifies” every route that gets created from collection pages (by using sindresorhus/slugify). Or in other words: If you have a route called src/pages/wholesome/{Animal.slogan}.js where slogan is I ♥ Dogs the final URL will be /wholesome/i-love-dogs. Gatsby will convert the field into a human-readable URL format while stripping it of invalid characters.

When you want to link to one of those pages, it may not always be clear how to construct the URL from scratch.

To address this issue, Gatsby automatically includes a gatsbyPath field on every type used by collection pages. The gatsbyPath field must take an argument of the filePath it is trying to resolve. This is necessary because it’s possible that one type is used in multiple collection pages.

There are some general syntax requirements when using the filePath argument:

  • The path must be an absolute path (starting with a /).
  • You must omit the file extension.
  • You must omit the src/pages prefix.
  • Your path must not include index.

gatsbyPath example

Assume that a Product type is used in two pages:

  • src/pages/products/{}.js
  • src/pages/discounts/{}.js

If you wanted to link to the products/{} and discounts/{} routes from your home page, you would have a component like this:

By using aliasing you can use gatsbyPath multiple times.

Creating client-only routes

Use client-only routes if you have dynamic data that does not live in Gatsby. This might be something like a user settings page, or some other dynamic content that isn’t known to Gatsby at build time. In these situations, you will usually create a route with one or more dynamic segments to query data from a server in order to render your page.

Syntax (client-only routes)

You can use square brackets ([ ]) in the file path to mark any dynamic segments of the URL. For example, in order to edit a user, you might want a route like /user/:id to fetch the data for whatever id is passed into the URL.

  • src/pages/users/[id].js will generate a route like /users/:id
  • src/pages/users/[id]/group/[groupId].js will generate a route like /users/:id/group/:groupId

Splat routes

Gatsby also supports splat (or wildcard) routes, which are routes that will match anything after the splat. These are less common, but still have use cases. As an example, suppose that you are rendering images from S3 and the URL is actually the key to the asset in AWS. Here is how you might create your file:

  • src/pages/image/[...awsKey].js will generate a route like /image/*awsKey
  • src/pages/image/[...].js will generate a route like /image/*

Three periods ... mark a page as a splat route. Optionally, you can name the splat as well, which has the benefit of naming the key of the property that your component receives.


The dynamic segment of the file name (the part between the square brackets) will be filled in and provided to your components on a props.params object. For example:

Example use cases

Have a look at the route-api example for more detail.

Collection route + fallback

By using a combination of a collection route with a client-only route, you can create a seamless experience when a user tries to visit a URL from the collection route that doesn’t exist (yet) for the collection item. Consider these two file paths:

  • src/pages/products/{}.js (collection route)
  • src/pages/products/[name].js (client-only route, fallback)

The collection route will create all available product pages at the time of the build. If you’re adding a new product you want to link to but only periodically building your site, you’ll need a fallback. By using a client-only route as a fallback you then can load the necessary information for the product on the client until you re-built your site.

Similarly, the fallback page could also be used for when a product doesn’t exist and you want to show some helpful information (like a 404 page).

Using one template for multiple routes

By placing the template/view for your routes into a reusable component you can display the same information under different routes. Take this example:

You want to display product information which is both accessible by name and SKU but has the same design. Create two file paths first:

  • src/pages/products/{}.js
  • src/pages/products/{Product.meta__sku}.js

Create a view component at src/view/product-view.js that takes in a product prop. Use that component in both collection routes, e.g.:

You can copy the same code to the src/pages/products/{Product.meta__sku}.js file.

Purely client-only app

If you want your Gatsby app to be 100% client-only, you can create a file at src/pages/[...].js to catch all requests. See the client-only-paths example for more detail.