Enea Xharja Logo

Convert an existing Gatsby Markdown blog to use MDX

I've recently released a new version of my personal website and I decided to convert my posts from an existing Gatsby Markdown format to MDX.

MDX is usually called the markdown for the component era and it's a great way to write a document using JSX in Markdown. Additionally, if you work on a React project, you can even import existing components inside your MDX files.

Let's get started!

Step 1

In order to use MDX with Gatsby, you need to install @mdx-js/mdx, @mdx-js/react and the official Gatsby plugin gatsby-plugin-mdx:

bash
1npm install --save @mdx-js/mdx @mdx-js/react gatsby-plugin-mdx

Step 2

Inside your gatsby-config.js file, replace gatsby-transformer-remark with gatsby-plugin-mdx:

diff
1- resolve: `gatsby-transformer-remark`,
2+ resolve: `gatsby-plugin-mdx`,

and plugins with gatsbyRemarkPlugins:

diff
1- plugins: [
2+ gatsbyRemarkPlugins: [

My cofigured gatsby-plugin-mdx looks like this:

js
1{
2 // parses Markdown files using MDX
3 resolve: `gatsby-plugin-mdx`,
4 options: {
5 gatsbyRemarkPlugins: [
6 {
7 // parses Markdown images using Remark
8 resolve: `gatsby-remark-images`,
9 options: {
10 maxWidth: 1200,
11 },
12 },
13 ],
14 },
15},

For reference, here is my entire gatsby-config file.

Step 3

Once we've refactored the gatsby-config.js file, it's time to work with gatsby-node.js. Here, we need to replace allMarkdownRemark with allMdx:

diff
1- allMarkdownRemark {
2+ allMdx {
diff
1- results.data.allMarkdownRemark.edges.forEach(({node}) => {
2+ results.data.allMdx.edges.forEach(({node}) => {

My gatsby-node.js file is available over here.

Step 4

The final step consists in refactoring the template file that is used to generate the blog posts. Head over to the template, in my case src/templates/postTemplate.js, and import MDXRenderer from the gatsby-plugin-mdx plugin that we installed earlier:

diff
1+ import { MDXRenderer } from 'gatsby-plugin-mdx'

Then, replace markdownRemark with mdx in the render() method:

diff
1- const { markdownRemark } = this.props.data
2+ const { mdx } = this.props.data

Finally, refactor the GraphQL query by using mdx instead of markdownRemark and body instead of html:

diff
1- markdownRemark(frontmatter: {
2+ mdx(frontmatter: {
diff
1- html
2+ body

The refactored post query will look like this:

js
1export const query = graphql`
2 query PostQuery($slug: String!) {
3 mdx(frontmatter: { slug: { eq: $slug } }) {
4 body
5 frontmatter {
6 title
7 date(formatString: "MMMM DD, YYYY")
8 slug
9 tags
10 }
11 }
12 }
13`;

and the template component:

js
1import React from 'react';
2import { graphql } from 'gatsby';
3import { MDXRenderer } from 'gatsby-plugin-mdx';
4
5import Layout from '../components/layout';
6import SEO from '../components/seo';
7
8const PostTemplate = ({
9 data: {
10 mdx: {
11 frontmatter: { title },
12 body,
13 },
14 },
15}) => (
16 <Layout>
17 <SEO title={title} />
18 <h1>{title}</h1>
19 <MDXRenderer>{body}</MDXRenderer>
20 </Layout>
21);
22
23export default PostTemplate;

For reference, here is my entire postTemplate component.

This is it! From now on, anytime you want to create a blog post, remember to use the .mdx extension.

© 2021 Enea Xharja