GatsbyTemplates.io

Fast, customizable templates for Gatsby

How to convert existing markdown blog to mdx

September 29, 2019

What is MDX? It’s like “JSX in markdown”. It lets you seamlessly write code in JSX in your markdown blog posts, for example.


Pros:

  • Declarative, more straightforward concept
  • Frontmatter and props support
  • All power of markdown with power of react components

Cons:

  • Non-informative error messages
  • Need to restart development server after each added/changed import component
  • Broken preview in vscode, github, gitlab(even with plugin)

Yes, it has some disadvantages. But nevertheless, I think mdx is the “new markdown”. All these problems are temporary, and since it really cutting-edge technology, having all those problems are absolutely natural. And if it’s not production-ready yet, for personal blog or site it’s absolute killer.
So, are you ready to discover future of tech blogging?
If you have no blog yet, just use gatsby-starter-blog-mdx, it has mdx support out of the box. Also you can check out official docs.
And for those who already have a blog and want to touch the awesomness of mdx, I will cover in details how to convert your markdown blog to mdx, let’s go.

Check out files in this repo as an example


  1. Install all dependencies:
npm i gatsby-plugin-mdx @mdx-js/mdx @mdx-js/react

Optionally, add eslint mdx plugin:

npm i -D eslint-plugin-mdx
  1. Update Gatsby lifecycle files:

In gatsby-config, scroll to gatsby-transformer-remark, and replace:


gatsby-transformer-remark -> gatsby-plugin-mdx
plugins -> gatsbyRemarkPlugins

using following example:

module.exports = {
  plugins: [
      ...
          {
      // line below changed
      resolve: `gatsby-plugin-mdx`, 
      options: {
        // line below changed
        gatsbyRemarkPlugins: [ 
          ....
          `gatsby-remark-smartypants`,
        ],
      },
    },
  ]
}

In gatsby-node, in GraphQL query replace “allMarkdownRemark” with “allMdx”, and “MarkdownRemark” with “Mdx”, so it will look like this:


exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions

  const blogPost = path.resolve(`./src/templates/blog-post.js`)
  const result = await graphql(
    `
      {
        allMdx(
          sort: { fields: [frontmatter___date], order: DESC }
          limit: 1000
        ) {
          edges {
            node {
                ...
    `
 const posts = result.data.allMdx.edges
                ...

if (node.internal.type === `Mdx`) {
    const value = createFilePath({ node, getNode })
    ...
  }
...

  1. Update post listing generation

In index.js(or where your posts listed), replace all “allMarkdownRemark” with “allMdx”:


class BlogIndex extends React.Component {
  render() {
    const { data } = this.props
    const posts = data.allMdx.edges

    return (
      <Layout location={this.props.location}>
        <SEO title="All posts" />
        <Bio />
        {posts.map(({ node }) => {
          ...
        })}
      </Layout>
    )
  }
}

export default BlogIndex

export const pageQuery = graphql`
  query {
    allMdx(sort: { fields: [frontmatter___date], order: DESC }) {
      edges {
        ...
      }
    }
  }
`

  1. Update blog post template

In your /src/templates/blog-post.js (or similar), you need to do following changes:

  • add import MDXRenderer
  • replace dangerouslySetInnerHTML with MDXRenderer
  • update query(change “markdown” to “mdx” and “html” to “body”)
import { MDXRenderer } from 'gatsby-plugin-mdx';

class BlogPostTemplate extends React.Component {
  render() {
    const post = this.props.data.mdx
    return (
      <Layout title={post.frontmatter.title}>
        <ContentSection
          title={post.frontmatter.title}
          subtitle={post.frontmatter.date}
          color="white"
          size="medium"
        >
          <article>

            <MDXRenderer>{post.body}</MDXRenderer>

            ....
    )
  }
}
export default BlogPostTemplate

export const pageQuery = graphql`
  query BlogPostBySlug($slug: String!) {
    mdx(fields: { slug: { eq: $slug } }) {
      id
      excerpt(pruneLength: 160)
      body
      frontmatter {
      ...
      }
    }
  }
`

  1. rename all your .md files to .mdx

  1. restart your development server:

gatsby develop

So far we changed:


gatsby-config
gatsby-node
blog-post.js
index.js(page)


Congratulations! you now have working mdx blog. Stay tuned.


Want some more awesome themes?

Templates for the new web

© gatsbytemplates.io