Enea Xharja

Software Engineer

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:

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.