How to convert existing markdown blog to mdx

vsevaseva profile image Vsevolod Updated on ・3 min read

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


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


  • 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: [ 

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(
          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 }) => {

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}>


export default BlogPostTemplate

export const pageQuery = graphql`
  query BlogPostBySlug($slug: String!) {
    mdx(fields: { slug: { eq: $slug } }) {
      excerpt(pruneLength: 160)
      frontmatter {
  1. rename all your .md files to .mdx
  1. restart your development server:
gatsby develop

So far we changed:





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

Check out our themes and articles about Gatsby and subscribe!

Posted on by:

vsevaseva profile



frontend dev who passionate about creating his own stuff


Editor guide

Great introduction, thank you! :)


Does it make easy to use custom components in Markdown? Like {% github name/repo no-readme %} ?