Chris.luChris.lu header image, displaying an 80s style landscape and sunset

MDX

a mad scientist mixing the content of a bottle labeled markdown with the content of another bottle labeled JSX into a big bowl labeled MDX

MDX is an extension of markdown, MDX means markdown + JSX, markdown is a markup language that can be used to format raw text, it was developed in 2004 by John Gruber in collaboration with Aaron Swartz and JSX is a syntax extension for JavaScript that lets you write HTML-like markup inside a JavaScript file

For an in-depth tutorial about how to use MDX with Next.js 15, check out my Tutorial: Next.js 15 MDX starterkit

What is MDX (behind the scenes)

MDX supports all markdown formatting elements that are also supported markdown, and even more formatting elements are available if you use plugins that add new elements like, for example, GFM (github flavored markdown) plugins

The big difference between markdown and MDX, is that MDX allows you to use JSX in your markdown content, meaning you can import and add JSX components (in our case React components) in your MDX content, for example, add a react component that is a comment section at the end of each article, or create a 3D animation using react three fiber and insert that react component in one of your articles, ...

Note: When I mention MDX on the following pages, I'm referring to MDX 3, the current version of MDX. The latest major release is MDX3 (October 24, 2023). The MDX v3 release blog post contains an overview of the few breaking changes and improvements. You can check the full MDX 3.0.0 changelog on the GitHub releases page, and if you are migrating from the previous version, you may want to have a look at the MDX v2 to v3 migration guide

All transformations happen thanks to utilities built on top of unified. It is the core project used to transform content with ASTs. The unified github repository gives us the following description:

Unified is an interface for parsing, inspecting, transforming, and serializing content through syntax trees

The specifications are all managed by the syntax-tree organization on github which is part of the unified collective, this is the home for several syntax tree specifications, the base syntax tree is called unist, unist is a universal syntax tree specification, it is part of the family of syntax trees called Abstract Syntax Treess hence the abbreviation ASTs, on top of unist you have the other syntax trees that we are interested in, the first one is called MDAST this is the specification that represents markdown in a syntax tree and the second one is called HAST which is the specification that represents HTML in a syntax tree, but because we use MDX and not pure markdown, the two syntax trees MDAST and HAST have supersets, the superset of MDAST is called MDXAST and the superset of HAST is called MDXHAST

MDAST and HAST are the syntax tree specifications, but the actual tools are Remark and Rehype.

remnark is a tool that transforms markdown with plugins, which they explain well in their README:

remark supports CommonMark by default. Non-standard markdown extensions can be enabled with plugins

rehype is similar to remark but has another purpose, Rehype is a tool that transforms HTML with plugins

MDX supports both remark and rehype plugins. More about plugins in the "using plugins to extend MDX" chapter

Note: if you want to experiment with MDX content, there is a great tool called MDX playground. You can experiment with MDX content, and it will help you visualize how MDX content gets transformed from MDAST (markdown AST) to HAST (HTML AST) to ESAST (javascript / JSX)

Collection of informative sources

VSCode extensions

There are a lot of VSCode extensions available for both MDX and markdown, open your extensions view in VSCode and search for MDX or markdown, or visit the online marketplace

In the following chapters I will introduce two extensions, one for MDX and one for markdown

Markdownlint extension for VSCode

Markdownlint is another popular extension, that is great when you quickly want to lint pure markdown files, like your projects README.md

Warning

it is not recommend to install the plugin if working with MDX as it will for example use markdown linting rules like the no-inline-html rule, but that rule is invalid when linting MDX (which allows using HTML elements inside of MDX content)

MDX extension for VSCode

There is a very useful MDX extension for VSCode that I recommend you install (if you work with MDX in VSCode)

The extension will read your .remarkrc(.js|.mjs) file (if you have one in the root of your workspace (project)) and apply the same rules you use on the command line inside of VSCode, meaning when there is a violation (based on your rules) it will underline the code that is responsible for the violation (green for warnings and red for errors)

The extension will also add MDX language support to VSCode. The support is experimental and there is a problem when setting the .mdx file association to be MDX instead of markdown, which is that VSCode will remove features like the markdown preview, I like to have the preview (even if it does NOT understand MDX and is only useful to get an idea of how the markdown parts will get rendered), the second disadvantage is that some themes have no support for MDX code highlighting colors, meaning when using some themes the MDX content will get displayed as simple text with no colors (or only a few)

install MDX for VSCode

Open the extensions view, then search for an extension named MDX (published my unified) and then click on the install button

Note

This extensions MDX language support is still experimental, but I had no major problems when using it

Unlike other extension, the MDX extension does not require any custom settings configuration, install it and you are done

file associations

To change the file association (matching a file extension with a language mode), first open an MDX file, then in the bottom right corner of VSCode you will either have "Markdown" or "MDX" set as default, if it is set to MDX then I recommend setting it to "Markdown"

Another option, if you have a .vscode/settings.json file in your workspace, is to edit that file and add the file association for MDX manually:

.vscode/settings.json
    "files.associations": {
        "*.mdx": "markdown"
    },
Note

by changing the file association to markdown, you are NOT disabling the MDX extension, it will continue to work and read your remark-link configuration file (if you have one in your workspace)

Frameworks with MDX support

All major frameworks support MDX either out of the box or via packages that you can install separately, Next.js has @next/mdx, but there are alternatives that I listed in the @next/mdx alternatives chapter, Astro has @astrojs/mdx, Remix devs often use mdx-bundler, and Gatsby has gatsby-plugin-mdx, there is also a popular project called Docusaurus which uses MDX, but it is more opinionated than the other frameworks as it focuses on building a documentation website

Next.js MDX & markdown packages

@next/mdx is an MDX package by the Next.js team

next mdx remote is an MDX package that has a feature @next/md does not, which is using remote MDX files or MDX content from a database

markdoc is a markdown only package (so no MDX), but they now have a Next.js plugin, which makes it easy to use markdoc with Next.js

contentlayer is an MDX package that was popular in the past (having earned >3k stars) but does not seem to get any updates anymore

Warning

contentlayer update: as this post suggests: development is currently halted

they now also added this warning in their readme:

Unfortunately Contentlayer is no longer maintained due to lack of funding. You can find a fork of the project here.