How to convert existing markdown blog to mdx
Tags: gatsby, react, markdown, mdx
Published: 2019-09-29 22:12:03

---
title: How to convert existing markdown blog to mdx
date: "2019-09-29T22:12:03.284Z"
description: "From markdown to mdx without tears and pain"
published: true
tags: gatsbyjs, react, markdown, mdx
---

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

<br/>

Pros:

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

<br/>

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)

<br/>

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.<br/>
So, are you ready to discover future of tech blogging?<br/>
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.<br/>
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](https://github.com/vse-volod/mdx-convert-guide)

<br/>

1. Install all dependencies:

```terminal
npm i gatsby-plugin-mdx @mdx-js/mdx @mdx-js/react
```

Optionally, add <a href="https://github.com/rx-ts/eslint-mdx">eslint mdx plugin</a>:

```console
npm i -D eslint-plugin-mdx
```

2. Update Gatsby lifecycle files:

<br/>

In __gatsby-config__, scroll to gatsby-transformer-remark, and replace:
<br/>

**gatsby-transformer-remark** -> **gatsby-plugin-mdx** <br/>
**plugins** -> **gatsbyRemarkPlugins** <br/><br/>

using following example:

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

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

<br/>

```javascript
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 })
    ...
  }
...
```

<br/>

3. Update post listing generation

<br/>

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

<br/>

```javascript
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 {
        ...
      }
    }
  }
`
```

<br/>

4. Update blog post template

<br/>

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")

```javascript
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 {
      ...
      }
    }
  }
`
```

<br/>

5. rename all your .md files to .mdx

<br/>

6. restart your development server:

<br/>

```
gatsby develop
```

<br/>

So far we changed:

<br/>

gatsby-config<br/>
gatsby-node<br/>
blog-post.js<br/>
index.js(page)<br/>

<br/>

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

[Check out our themes and articles about Gatsby and subscribe!](https://gatsbytemplates.io/)