Convert an existing Gatsby Markdown blog to use MDX

Updated: August 4, 2020

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:

npm 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:

- resolve: `gatsby-transformer-remark`,
+ resolve: `gatsby-plugin-mdx`,

and plugins with gatsbyRemarkPlugins:

- plugins: [
+ gatsbyRemarkPlugins: [

My configured gatsby-plugin-mdx looks like this:

gatsby-config.js
{
// parses Markdown files using MDX
resolve: `gatsby-plugin-mdx`,
options: {
gatsbyRemarkPlugins: [
{
// parses Markdown images using Remark
resolve: `gatsby-remark-images`,
options: {
maxWidth: 1200,
},
},
],
},
},

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:

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

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:

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

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

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

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

- markdownRemark(frontmatter: {
+ mdx(frontmatter: {
- html
+ body

The refactored post query will look like this:

src/templates/postTemplate.js
export const query = graphql`
query PostQuery($slug: String!) {
mdx(frontmatter: { slug: { eq: $slug } }) {
body
frontmatter {
title
date(formatString: "MMMM DD, YYYY")
slug
tags
}
}
}
`;

and the template component:

src/templates/postTemplate.js
import React from "react";
import { graphql } from "gatsby";
import { MDXRenderer } from "gatsby-plugin-mdx";

import Layout from "../components/layout";
import SEO from "../components/seo";

const PostTemplate = ({
data: {
mdx: {
frontmatter: { title },
body,
},
},
}) => (
<Layout>
<SEO title={title} />
<h1>{title}</h1>
<MDXRenderer>{body}</MDXRenderer>
</Layout>
);

export default PostTemplate;

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