Adding MDX Pages
Examples
Introduction
MDX is Markdown for the component era. It lets you write JSX embedded inside Markdown. This combination allows you to use Markdown’s terse syntax (such as # Heading
) for your content and JSX for more advanced or reusable components.
This is useful in content-driven sites where you want the ability to introduce components like charts or alerts without having to configure a plugin. MDX also shines in interactive blog posts, documenting design systems, or long form articles with immersive or dynamic interactions.
Prerequisites
- A Gatsby project set up with
gatsby@4.21.0
or later.
Installation and configuration
If you already have a Gatsby site that you’d like to add MDX to, you can follow these steps for configuring the gatsby-plugin-mdx plugin.
Starting a new project? Skip the setup and create a new project using
npm init gatsby
Choose the option “Add Markdown and MDX support” to add the necessary MDX dependencies.
Already using Remark? Check out the How-To Guide on Migrating from Remark to MDX.
Install the required dependencies:
Update your
gatsby-config.js
to usegatsby-plugin-mdx
andgatsby-source-filesystem
Restart your local development server by running
gatsby develop
.
Writing pages in MDX
After installing gatsby-plugin-mdx
, MDX files located in the src/pages
directory will automatically be turned into pages.
gatsby-plugin-mdx
looks for MDX files and automatically transpiles them so that Gatsby can render them. Make sure to parse these MDX files withgatsby-source-filesystem
, otherwise they can’t be located.
Pages are rendered at a URL that is constructed from the filesystem path inside src/pages
. For example, an MDX file at src/pages/awesome.mdx
will result in a page being rendered at yoursite.com/awesome
.
Create a new .mdx
file in the src/pages
directory (e.g. src/pages/chart-info.mdx
). You can use Markdown syntax to add different HTML elements.
Using frontmatter in MDX
By default, gatsby-plugin-mdx
supports frontmatter
so you can define things like titles and paths to use in your GraphQL
queries. You can declare frontmatter at the beginning of your MDX document:
You can then query for this frontmatter data with GraphQL:
Frontmatter is also available in props.pageContext.frontmatter
and
can be accessed in blocks of JSX in your MDX document:
Importing JSX components into MDX documents
MDX allows you to use React components alongside Markdown. You can import components from third-party libraries (like theme-ui
) to take advantage of pre-built functionality like data visualizations, email signup forms, or call-to-action buttons. You can also import and reuse your own React components and even other MDX documents.
To import a component, add a JavaScript import
statement to your MDX file. Once you’ve imported a component, you can use it in the body of your MDX file the same way you’d normally use a React component:
Note: If you would like to include frontmatter metadata and import components, the frontmatter needs to appear at the top of the file and then imports can follow.
Importing MDX files into JSX components
You can also import MDX files into JSX components. For example, if you have a MDX file inside src/content
that you want to include into a React component, you’ll first need to make sure that gatsby-plugin-mdx
can transpile that file. For this you have to point gatsby-source-filesytem
to this folder:
Afterwards you’ll be able to use the MDX file (the .mdx
file extension in the import is necessary) like so:
Defining a layout
You can use regular layout components to apply layout to your sub pages.
To inject them, you have several options:
- Use the
wrapPageElement
API including its SSR counterpart. - Add an
export default Layout
statement to your MDX file, see MDX documentation on Layout. - When using the
createPage
action to programatically create pages, you should use the following URI pattern for your page component:your-layout-component.js?__contentFilePath=absolute-path-to-your-mdx-file.mdx
. To learn more about this, head to the programmatically creating pages section just below.
Make components available globally as shortcodes
To avoid having to import the same component inside of every MDX document you author, you can add components to an MDXProvider
to make them globally available in MDX pages. This pattern is sometimes referred to as shortcodes.
All MDX components passed into the components
prop of the MDXProvider
will be made available to MDX documents that are nested under the provider. You have multiple options on how to use this layout component in your site. Learn more in the layout section of the gatsby-plugin-mdx
README.
Now, you can include components in your MDX without importing them:
Because the <Message />
and <Chart />
components were passed into the provider, they are available for use in all MDX documents.
Programmatically creating pages
Sometimes you want to be able to programmatically create pages using MDX content that lives at arbitrary locations outside of src/pages
or in a remote CMS.
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
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.
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.
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 from the frontmatter
you defined.
Note: You can open up a GraphiQL console for query testing in your browser at
http://localhost:8000/___graphql
For further reading, check out the createPages API.
Make a layout template for your posts
You can create a file called post.jsx
in src/templates
- this component will be rendered as the template for every post. Now, create a component that accepts your compiled MDX content via children
and uses GraphQL data
to show the title:
Now you need to tell gatsby-plugin-mdx
to use your PageTemplate
component as layout for your post. To do this, you need to change the structure of the component
URI in your createPage
call:
From an absolute path to your component (e.g. /absolute/path/to/layout-component.js
) to a path that contains a query parameter __contentFilePath
(e.g. /absolute/path/to/layout-component.js?__contentFilePath=/absolute/path/to/content.mdx
).
Please note: While you can create your layout templates as TypeScript files (e.g. post.tsx
) you can’t actually use most TypeScript syntax. This is because the underlying acorn parser only understands modern JS and JSX syntax.
However, you can import your TypeScript types from another file instead. In most cases this should then work — if you’re still encountering an “Unexpected token” error, try removing TypeScript syntax piece by piece to see why it breaks.
Change your gatsby-node.js
as following:
That’s it, you’re done. Run gatsby develop
to see your posts wrapped with post.jsx
.
Adding additional fields to your GraphQL MDX nodes
To extend your GraphQL nodes, you can use the onCreateNode
API.
You can find examples in the README of gatsby-plugin-mdx
.
gatsby-remark-*
and remark
plugins
gatsby-plugin-mdx
can also use gatsby-remark-*
(e.g. gatsby-remark-images
) and remark
(e.g. remark-gfm
) plugins. You can learn more about this in the configuration section of gatsby-plugin-mdx
’s README.