Website MDX setup

Last updated:

What better way to document MDX than with MDX?


There were a few moving parts involved with setting up MDX so it might make sense to have them written down.

What's MDX?

Not in scope here - but it's essentially React in Markdown.

How do we make it work?

Page creation

Website pages are automatically created for all MD and MDX files using Gatsby's createPages API. Slugs are automatically generated based on the file title, and the design template for each page is determined based on the folder the file resides in.

Design templates

There are currently 5 templates:

  • Handbook / Docs - Files located in contents/handbook and contents/docs
  • Blog post - Files located in contents/blog
  • Blog category - Automatically created based on categories used in blog posts
  • Customer - Files located in contents/customers
  • Plain - All other files located in contents

Each template is passed a unique automatically generated ID that is used to query the data contained inside of the post.

The GraphQL query inside of each template will return everything we need, from content to frontmatter, and we use the component MDXRenderer to render the body, and MDXProvider to pass some context that is available to all MDX pages.

In this case, we pass references to components that can then be used without imports directly on MDX pages, like this hedgehog:

Because of the components passed to MDXProvider, I can include this hedgehog by just adding <BasicHedgehogImage /> in my MDX file - no import needed.

However, if I want to include something from a module, I can also do so. Here's how one would insert a spinner component from AntD:

import { Spin } from 'antd'
## Some Markdown
<Spin />

Currently, almost every component on the site is available automatically. This will eventually change because it causes some performance issues. For now, if you need a reference for which components you should be using in your MDX, check out the Storybook page.


The mdxImportGen.js script handles global MDX imports automatically. This is currently a quick implementation that can improve and be made more robust in the pre-commit process. Essentially, it prepares a file based on all the components in our src/components directory which is then used to pass the components to MDXProvider, making them available everywhere.

Doing globally available imports this way was important for 3 main reasons:

  • Relative imports in MDX can be annoying
  • Keeping MDX files clean
  • Making MDX a nice experience even for less technical people that update our website