Skip to main content

Programmatically Creating Pages

Sometimes you want to be able to programmatically access data from files in src/pages/ or create pages using MDX content that lives at arbitrary locations outside of src/pages/ or in remote CMSes.

For instance, let’s say you have a Gatsby website, and you want to add support for MDX so you can start your blog. The posts will live in content/posts/. You can do this with the help of gatsby-source-filesystem and createPages in gatsby-node.js.

Source MDX pages from the filesystem

To let Gatsby know that you’ll be working with MDX content you need to add gatsby-plugin-mdx to the plugins array in your gatsby-config.js file.

You’ll need to use gatsby-source-filesystem and tell it to source “posts” from a folder called content/posts located in the project’s root.

Note: gatsby-plugin-mdx uses .mdx by default as a file extension to recognize which files to use. You can also use .md as a file extension if you want.

You can read about gatsby-source-filesystem if you’d like to learn more.

Add MDX files

Before you can write any GraphQL queries and programmatically create pages, you need to add some content.

Make a folder called content/posts and create two files in it called blog-1.mdx and blog-2.mdx. You can do this on the command line in a terminal by using the following commands from the root of your project.

Note: mkdir -p path/to/a/directory will create every folder in the path if it does not exist.

touch <filename> will create an empty file named <filename>. The brackets ({}) are an expansion which means you can create multiple files in one command.

Open up each of the files you just created and add some content.

Generate slugs

Since MDX posts are being sourced outside of src/pages, each post needs to be given a slug which tells Gatsby the URL to render to.

If you want to set the URLs in your frontmatter, you can skip this step.

The value in the createNodeField call is the URL you’ll use later to set up our page. /blog${value} is a template string that will result in:

createFilePath is a function from gatsby-source-filesystem that translates file paths to usable URLs.

onCreateNode is a Gatsby lifecycle method that gets called whenever a new node is created. In this case only MDX nodes are touched.

Create pages from sourced MDX files

In order to create pages from the sourced MDX files, you need to construct a query that finds all MDX nodes and pulls out the slug field added earlier.

Note: You can open up a GraphiQL console for query testing in your browser at http://localhost:8000/___graphql

If you skipped the last step and want to use frontmatter for your slugs instead of the generated field, replace fields with frontmatter.

For further reading, check out the createPages API.

Make a template for your posts

You can create a file called posts-page-layout.js in src/components - this component will be rendered as the template for all posts. There’s a component, MDXRenderer which is used by gatsby-plugin-mdx that will be used to render any programmatically accessed MDX content.

For now, to update imports within .mdx files, you should rerun your Gatsby development environment. Otherwise, it will raise a ReferenceError. To import things dynamically, you can use the MDXProvider component and provide it all the common components you’ll be using, such as Link.

First, create a component that accepts the queried MDX data (which will be added in the next step).

Then, write a query that uses id which is passed through the context object in createPage. GraphQL requires you to declare the type of arguments at the top of the query before they’re used.

When you put the component and page query all together, the component should look like:

That’s it, you’re done. Run gatsby develop and enjoy your new MDX powers.

Now you have all the pieces you need to programmatically create pages with Gatsby and gatsby-plugin-mdx. You can check out our other guides to find out more about all of the cool stuff you can do with gatsby-plugin-mdx.

Bonus: Make a blog index


Edit this page on GitHub