Advanced routing patterns for creating data-driven pages and client-side routes using special file naming conventions. The File System Route API enables automatic page generation from GraphQL data sources.
Create pages programmatically from GraphQL data using {Model.field} syntax in file names.
/**
* Collection route syntax: {NodeType.field}
* File: /blog/{MarkdownRemark.frontmatter__slug}.js
* Creates: /blog/my-post/, /blog/another-post/, etc.
*
* @param NodeType - GraphQL node type (e.g. MarkdownRemark, File, ContentfulBlogPost)
* @param field - Node field path using __ for nested fields (e.g. frontmatter__slug)
*/Usage Examples:
// File: src/pages/blog/{MarkdownRemark.frontmatter__slug}.js
// Creates pages like: /blog/my-first-post/, /blog/getting-started/
import React from "react";
import { graphql } from "gatsby";
export default function BlogPost({ data }) {
const { markdownRemark } = data;
return (
<div>
<h1>{markdownRemark.frontmatter.title}</h1>
<div dangerouslySetInnerHTML={{ __html: markdownRemark.html }} />
</div>
);
}
export const query = graphql`
query($id: String!) {
markdownRemark(id: { eq: $id }) {
html
frontmatter {
title
slug
}
}
}
`;// File: src/pages/products/{ShopifyProduct.handle}.js
// Creates pages like: /products/t-shirt/, /products/sneakers/
import React from "react";
import { graphql } from "gatsby";
export default function Product({ data }) {
const { shopifyProduct } = data;
return (
<div>
<h1>{shopifyProduct.title}</h1>
<p>${shopifyProduct.priceRange.minVariantPrice.amount}</p>
</div>
);
}
export const query = graphql`
query($id: String!) {
shopifyProduct(id: { eq: $id }) {
title
handle
priceRange {
minVariantPrice {
amount
}
}
}
}
`;Create nested URL structures using multiple collection segments.
/**
* Nested collection route syntax
* File: /blog/{MarkdownRemark.frontmatter__category}/{MarkdownRemark.frontmatter__slug}.js
* Creates: /blog/tutorials/getting-started/, /blog/news/announcement/
*/Usage Example:
// File: src/pages/blog/{MarkdownRemark.frontmatter__category}/{MarkdownRemark.frontmatter__slug}.js
import React from "react";
import { graphql } from "gatsby";
export default function CategorizedPost({ data, params }) {
const { markdownRemark } = data;
const { category, slug } = params; // Available via context
return (
<div>
<nav>Category: {category}</nav>
<h1>{markdownRemark.frontmatter.title}</h1>
<div dangerouslySetInnerHTML={{ __html: markdownRemark.html }} />
</div>
);
}Handle GraphQL union types in collection routes using (UnionType) syntax.
/**
* Union type collection route syntax
* File: /content/{ContentfulBlogPost.slug__(ContentfulBlogPost)__category}.js
* Handles: ContentfulBlogPost union types with specific field access
*/Create client-side routes that bypass Gatsby's static generation using [param] syntax.
/**
* Client-only route syntax: [param] or [...]
* File: /app/[...].js -> /app/* (catch-all client route)
* File: /user/[id].js -> /user/:id (parameterized client route)
*
* @param param - Parameter name for React Router-style routing
* @param ... - Catch-all parameter for wildcard routes
*/Usage Examples:
// File: src/pages/app/[...].js
// Handles all routes under /app/* on the client
import React from "react";
import { Router } from "@reach/router";
import Dashboard from "../components/Dashboard";
import Profile from "../components/Profile";
export default function App() {
return (
<Router basepath="/app">
<Dashboard path="/" />
<Profile path="/profile" />
</Router>
);
}// File: src/pages/user/[id].js
// Handles routes like /user/123, /user/abc on the client
import React from "react";
import { useParams } from "@reach/router";
export default function UserProfile() {
const { id } = useParams();
return <h1>User Profile: {id}</h1>;
}Programmatically generate paths for collection routes using the gatsbyPath field.
/**
* GatsbyPath GraphQL field - automatically added to node types with collection routes
* @param filePath - Collection route template path
* @returns Generated URL path for the node
*/
interface NodeWithGatsbyPath {
gatsbyPath(filePath: String!): String;
}Usage Examples:
// Query example
export const query = graphql`
query {
allMarkdownRemark {
nodes {
id
frontmatter {
title
}
# Generate path using collection route template
gatsbyPath(filePath: "/blog/{MarkdownRemark.frontmatter__slug}")
}
}
}
`;// Component usage
import React from "react";
import { Link, graphql } from "gatsby";
export default function BlogIndex({ data }) {
return (
<div>
<h1>Blog Posts</h1>
{data.allMarkdownRemark.nodes.map((post) => (
<div key={post.id}>
<Link to={post.gatsbyPath}>
{post.frontmatter.title}
</Link>
</div>
))}
</div>
);
}How collection route paths are generated from node data.
/**
* Main path derivation function for converting collection routes to URLs
* @param filePath - Template file path with {Model.field} syntax
* @param nodeData - GraphQL node data containing field values
* @param reporter - Gatsby reporter for logging errors
* @param slugifyOptions - URL slugification options
* @param getFieldValue - Optional field value accessor for GraphQL context
* @returns Object with generated path and error count
*/
function derivePath(
filePath: string,
nodeData: Record<string, any>,
reporter: Reporter,
slugifyOptions?: ISlugifyOptions,
getFieldValue?: (node: Record<string, any>, fieldPath: string) => any
): Promise<{ derivedPath: string; errors: number }>;Path Generation Process:
{Model.field} patternHow to access nested fields in collection routes.
/**
* Field access patterns
* - Simple field: {Model.field}
* - Nested field: {Model.parent__child}
* - Array access: {Model.tags[0]}
* - Union type: {Model.field__(UnionType)__subfield}
*/Examples:
// Simple field access
// File: {MarkdownRemark.frontmatter__slug}.js
// Accesses: node.frontmatter.slug
// Nested field access
// File: {File.parent__(MarkdownRemark)__frontmatter__title}.js
// Accesses: node.parent.frontmatter.title (with union type check)
// Complex nested access
// File: {ContentfulBlogPost.author__profile__slug}.js
// Accesses: node.author.profile.slugThe plugin validates route templates and reports errors for invalid patterns.
/**
* Route validation errors
*/
enum RouteValidationErrors {
/** Invalid collection route GraphQL syntax */
CollectionGraphQL = "12102",
/** Invalid collection route structure */
CollectionBuilder = "12103",
/** Path generation failed */
GeneratePath = "12104",
/** Invalid collection path format */
CollectionPath = "12105"
}