File: README.md
Markdown for the component era
MDX is an authorable format that lets you seamlessly write JSX in
your markdown documents.
You can import components, such as interactive charts or alerts, and embed them
within your content.
This makes writing long-form content with components a blast.
π
import {Chart} from './snowfall.js'
export const year = 2013
# Last yearβs snowfall
In {year}, the snowfall was above average.
It was followed by a warm spring which caused
flood conditions in many of the nearby rivers.
<Chart year={year} color="#fcb32c" />See Β§ What is MDX for more info on the
format.
See Β§ Playground to try it out.
What is this?
This GitHub repository contains several packages for compiling the MDX format to
JavaScript, integrating with bundlers such as webpack and Rollup, and for using
it with frameworks such as React, Preact, and Vue.
See Β§ Getting started for how to
integrate MDX into your project.
Security
See Β§ Security on our site for information.
Contribute
See Β§ Contribute on our site for ways to get started.
See Β§ Support for ways to get help.
This project has a code of conduct.
By interacting with this repository, organization, or community you agree to
abide by its terms.
Sponsor
See Β§ Sponsor on our site for how to help financially.
| Vercel
| Motif
| HashiCorp
| GitBook
| Gatsby
| | | | |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Netlify
| Coinbase
| ThemeIsle
| Expo
| Boost Note
| Markdown Space
| Holloway
| | |
| You? | | | | | | | | |
License
File: Readme.md
Markdown for the component era
MDX is an authorable format that lets you seamlessly write JSX in
your markdown documents.
You can import components, such as interactive charts or alerts, and embed them
within your content.
This makes writing long-form content with components a blast.
π
import {Chart} from './snowfall.js'
export const year = 2013
# Last yearβs snowfall
In {year}, the snowfall was above average.
It was followed by a warm spring which caused
flood conditions in many of the nearby rivers.
<Chart year={year} color="#fcb32c" />See Β§ What is MDX for more info on the
format.
See Β§ Playground to try it out.
What is this?
This GitHub repository contains several packages for compiling the MDX format to
JavaScript, integrating with bundlers such as webpack and Rollup, and for using
it with frameworks such as React, Preact, and Vue.
See Β§ Getting started for how to
integrate MDX into your project.
Security
See Β§ Security on our site for information.
Contribute
See Β§ Contribute on our site for ways to get started.
See Β§ Support for ways to get help.
This project has a code of conduct.
By interacting with this repository, organization, or community you agree to
abide by its terms.
Sponsor
See Β§ Sponsor on our site for how to help financially.
| Vercel
| Motif
| HashiCorp
| GitBook
| Gatsby
| | | | |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Netlify
| Coinbase
| ThemeIsle
| Expo
| Boost Note
| Markdown Space
| Holloway
| | |
| You? | | | | | | | | |
License
File: readme.md
Markdown for the component era
MDX is an authorable format that lets you seamlessly write JSX in
your markdown documents.
You can import components, such as interactive charts or alerts, and embed them
within your content.
This makes writing long-form content with components a blast.
π
import {Chart} from './snowfall.js'
export const year = 2013
# Last yearβs snowfall
In {year}, the snowfall was above average.
It was followed by a warm spring which caused
flood conditions in many of the nearby rivers.
<Chart year={year} color="#fcb32c" />See Β§ What is MDX for more info on the
format.
See Β§ Playground to try it out.
What is this?
This GitHub repository contains several packages for compiling the MDX format to
JavaScript, integrating with bundlers such as webpack and Rollup, and for using
it with frameworks such as React, Preact, and Vue.
See Β§ Getting started for how to
integrate MDX into your project.
Security
See Β§ Security on our site for information.
Contribute
See Β§ Contribute on our site for ways to get started.
See Β§ Support for ways to get help.
This project has a code of conduct.
By interacting with this repository, organization, or community you agree to
abide by its terms.
Sponsor
See Β§ Sponsor on our site for how to help financially.
| Vercel
| Motif
| HashiCorp
| GitBook
| Gatsby
| | | | |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Netlify
| Coinbase
| ThemeIsle
| Expo
| Boost Note
| Markdown Space
| Holloway
| | |
| You? | | | | | | | | |
License
File: docs/blog/conf.mdx
import {Note} from '../_component/note.jsx'
export const info = {
author: [
{github: 'johno', name: 'John Otander'}
],
modified: new Date('2025-01-27'),
published: new Date('2020-07-31')
}
MDXConf
MDXConf is a free and online conference for the MDX community.
Whether youβre just learning about MDX or an expert, thereβll be something for
you! {/* more */}
August 24th, 2020 at 8am PDT/3pm UST Online β’ Free
Watch
The conference is now over, but you can still watch the recordings!
About
Join us for the first MDX conference!
Weβll stream it directly to you, for free.
MDX has grown rapidly since the first commit two and a half years ago.
Weβd like to celebrate our accomplishments so far, and talk about what lies
ahead.
Weβve got lots of plans.
Learn how MDX increases developer productivity, improves educational
content authoring, and even peek behind the curtains to see how MDX works.
Speakers
Chris Biscardi
]
Keynote: The past, present, and future of MDX
Monica Powell
Migrating to MDX
Laurie Barth
MDX v2 syntax
Cole Bemis
Demystifying MDX
Prince Wilson
Personal site playgrounds
Kathleen McMahon
Digital gardening with MDX magic
Rodrigo Pombo
The X in MDX
Jonathan Bakebwa
MDX and Vue/Nuxt
Sign up
FAQ
What if I canβt make it on August 24th?
Weβll miss you, but you wonβt miss out!
All talks will be recorded and released the day of the conference.
You can catch up with the talks, or rewatch them, whenever convenient.
Will the talks be transcribed?
Yes.
Is there a code of conduct?
Absolutely.
Weβre dedicated to providing a harassment-free experience for everyone.
We will not tolerate harassment of participants in any form.
Weβve adopted the Party Corgi Networkβs Code of Conduct.
We will have moderators to ensure that the code of conduct is followed.
Do you have a different question?
Reach out to us.
File: docs/blog/custom-pragma.mdx
import {Note} from '../_component/note.jsx'
export const info = {
author: [
{github: 'christopherbiscardi', name: 'Chris Biscardi'}
],
modified: new Date('2021-11-01'),
published: new Date('2019-03-11')
}
Custom pragma
MDXTag, for those that arenβt aware, is a critical piece in the way
MDX replaces HTML primitives like and `<h1>` with custom React Components. [Iβve previously written](https://www.christopherbiscardi.com/post/codeblocks-mdx-and-mdx-utils) about the way `MDXTag` works when trying to replace the tag
with a custom code component.
mdx-utils
contains the methodology for pulling the props around appropriately
through the MDXTag elements that are inbetween pre and code.
{/* more */}
exports.preToCodeBlock = preProps => {
if (
// children is MDXTag
preProps.children &&
// MDXTag props
preProps.children.props &&
// if MDXTag is going to render a <code>
preProps.children.props.name === 'code'
) {
// we have a <code> situation
const {
children: codeString,
props: {className, ...props}
} = preProps.children.props
return {
codeString: codeString.trim(),
language: className && className.split('-')[1],
...props
}
}
return undefined
}So MDXTag is a real Component in the middle of all of the other MDX
rendered elements.
All of the code is included here for reference.
import React, {Component} from 'react'
import {withMDXComponents} from './mdx-provider'
const defaults = {
inlineCode: 'code',
wrapper: 'div'
}
class MDXTag extends Component {
render() {
const {
name,
parentName,
props: childProps = {},
children,
components = {},
Layout,
layoutProps
} = this.props
const Component =
components[`${parentName}.${name}`] ||
components[name] ||
defaults[name] ||
name
if (Layout) {
return (
<Layout components={components} {...layoutProps}>
<Component {...childProps}>{children}</Component>
</Layout>
)
}
return <Component {...childProps}>{children}</Component>
}
}
export default withMDXComponents(MDXTag)MDXTag is used in the hast to estree conversion,
which is the final step in the MDX AST pipeline.
Every renderable element is wrapped in an MDXTag, and MDXTag handles
rendering the element later.
return `<MDXTag name="${node.tagName}" components={components}${
parentNode.tagName ? ` parentName="${parentNode.tagName}"` : ''
}${props ? ` props={${props}}` : ''}>${children}</MDXTag>`A concrete example
The following MDX
# a title
and such
testingturns into the following React code
export default ({components, ...props}) => (
<MDXTag name="wrapper" components={components}>
<MDXTag name="h1" components={components}>{`a title`}</MDXTag>{' '}
<MDXTag name="pre" components={components}>
<MDXTag
name="code"
components={components}
parentName="pre"
props={{metaString: null}}
>{`and such `}</MDXTag>
</MDXTag>{' '}
<MDXTag name="p" components={components}>{`testing`}</MDXTag>
</MDXTag>
)resulting in the following HTML
<h1>a title</h1>
`and such`
testingcreateElement
With the new approach, the above MDX transforms into this new React code
const layoutProps = {}
export default function MDXContent({components, ...props}) {
return (
<MDXLayout
{...layoutProps}
{...props}
components={components}
mdxType="MDXLayout"
>
<h1>{`a title`}</h1>
<code parentName="pre" {...{}}>{`and such
`}</code>
{`testing`}
</MDXLayout>
)
}
MDXContent.isMDXComponent = trueNotice how now the React elements are plainly readable without
wrapping MDXTag.
Now that weβve cleaned up the intermediary representation, we need to
make sure that we have the same functionality as the old MDXTag.
This is done through a custom createElement implementation.
Typically when using React, we use React.createElement to render the elements
on screen.
This is even true if youβre using JSX because JSX tags such as `` compile
to createElement calls.
So this time instead of using React.createElement weβll be using our own.
Reproduced here is our createElement function and the logic for how
we decide whether or not MDX should take over the rendering of thecreateElement call.
export default function (type, props) {
const args = arguments
const mdxType = props && props.mdxType
if (typeof type === 'string' || mdxType) {
const argsLength = args.length
const createElementArgArray = new Array(argsLength)
createElementArgArray[0] = MDXCreateElement
const newProps = {}
for (let key in props) {
if (hasOwnProperty.call(props, key)) {
newProps[key] = props[key]
}
}
newProps.originalType = type
newProps[TYPE_PROP_NAME] = typeof type === 'string' ? type : mdxType
createElementArgArray[1] = newProps
for (let i = 2; i < argsLength; i++) {
createElementArgArray[i] = args[i]
}
return React.createElement.apply(null, createElementArgArray)
}
return React.createElement.apply(null, args)
}Vue
One really cool application of the new output format using a customcreateElement is that we can now write versions of it for Vue and other
frameworks.
Since the pragma insertion is the responsibility of the webpack (or other
bundlers) loader, swapping the pragma can be an option in mdx-loader as long as
we have a Vue createElement to point to.
File: docs/blog/index.mdx
{
/**
- @import {Item} from '../_component/sort.js'
*/
/**
- @typedef Props
- @property {Item} navigationTree
*/
}
import assert from 'node:assert/strict'
import {BlogGroup} from '../_component/blog.jsx'
export const info = {
author: [{name: 'MDX Contributors'}],
modified: new Date('2024-07-04'),
published: new Date('2021-11-01')
}
export const navExcludeGroup = true
export const navigationSortItems = 'navSortSelf,meta.published:desc'
export const navSortSelf = 7
Blog
The latest news about MDX.
{
(function () {
const navigationTree = props.navigationTree
const category = navigationTree.children.find(function (item) {
return item.name === '/blog/'
})
assert(category)
return (
<nav>
</nav>
) })()
}
File: docs/blog/shortcodes.mdx
import {Note} from '../_component/note.jsx'
export const info = {
author: [
{github: 'johno', name: 'John Otander'}
],
modified: new Date('2021-11-01'),
published: new Date('2019-05-14')
}
Shortcodes
An exciting new feature in MDX v1 is global shortcodes.
This allows you to expose components to all of your documents in your app or
website.
This is a useful feature for common components like YouTube embeds, Twitter
cards, or anything else frequently used in your documents.
{/* more */}
If you have an application wrapper for your MDX documents
you can add in components with the MDXProvider:
import React from 'react'
import {MDXProvider} from '@mdx-js/react'
import {TomatoBox, Twitter, YouTube} from './ui'
const shortcodes = {TomatoBox, Twitter, YouTube}
export default ({children}) => (
<MDXProvider components={shortcodes}>{children}</MDXProvider>
)Then, any MDX document thatβs wrapped in App has access to YouTube,Twitter, and TomatoBox.
Shortcodes are nothing more than components, so you can reference them anywhere
in an MDX document with JSX.
# Hello world!
Hereβs a YouTube shortcode:
<YouTube tweetId="1234" />
Hereβs a YouTube shortcode wrapped in TomatoBox:
<TomatoBox>
<YouTube videoId="1234" />
</TomatoBox>Thatβs it.
π π
Huge thanks to Chris Biscardi
for building out most of this functionality.
File: docs/blog/v1.mdx
import {Note} from '../_component/note.jsx'
export const info = {
author: [
{github: 'johno', name: 'John Otander'}
],
modified: new Date('2025-01-27'),
published: new Date('2019-04-11')
}
MDX goes stable
Itβs been a year and a half since the first MDX commit and a year since MDX was
first announced at ZEIT Day.
MDX is a radical paradigm shift in how to write immersive content using
components.
Itβs an open, authorable format that
makes it fun to write again.
{/* more */}
Since announcing MDX weβve been working on numerous bug fixes, new features,
better parsing, and integration tests.
Now, we think itβs ready.
Weβre happy to finally release v1!
π Whatβs new?
Hereβs a rough breakdown on what weβve been working on:
Parsing
MDX document parsing is significantly improved.
We wonβt get into the nitty gritty here, but weβve seen how MDX is used in
real-world projects, integrated the edge cases we came across into our test
suite, and now handle JSX, imports, and exports much more intuitively.
Please open an issue if you find a case we havenβt covered!πΈ
remark-mdx
remark-mdx is the syntactic extension for MDX in remark.
It provides the parsing functionality for MDX as a
remark plugin.
That sounds a bit meta.
What it means is that before we had the syntax parsing bits in the library
(unusable from the outside), and now itβs externalized (usable from the
outside).
This is useful if you want to inspect or transform MDX documents.
For example, it allows tools like prettier to use the exact same parser used by
MDX core.
Or you could use remark-mdx in combination with
remark-lint to check your MDX.
Custom pragma
With v1 weβve moved away from using MDXTag and are using a custom pragma which
wraps React.createElement.
We decided to update this approach so the JSX output is more legible,
lighterweight, and more customizable.
This means MDX can be used with any React, Vue, Preact, or any other library
with JSX support.
Special thanks to @christopherbiscardi
for implementing this feature.
π Documentation
Good libraries need great docs, so weβve been working on adding content and
improving the overall documentation website experience.
- Search (thanks Algolia)
- Guides
- Automatic deployment via ZEIT
- Custom Gatsby theme
- Reorganization of docs for intuitiveness
- Full page rewrites to improve clarity
Special thanks to @jxnblk and
@wooorm for their help improving the docs and
updating the build tooling.
Breaking changes
In order to make some improvements we were forced to introduce a few breaking
changes.
These were the result of real-world production testing and feedback.
The community has evolved and weβve come up with newer, better ideas over the
last year.
We have made sure the impact is small and have written a full migration guide.
- π¨
@mdx-js/tagis replaced by@mdx-js/reactand an@mdxpragma
β migration guide - MDXProvider now merges component contexts when nested
β migration guide - React support now requires
>= 16.8in@mdx-js/react
β migration guide
Read the full v1 migration guide
Deprecations
We only needed to introduce one deprecation.
The mdPlugins and hastPlugins options have been renamed remarkPlugins andrehypePlugins respectively.
For the time being we will issue a warning when the old options are used.
In v2, the old options will be removed.
π Growth
A major release is always a good time to take a step back and reflect on whatβs
been happening in terms of growth and the greater community.
The ecosystem surrounding MDX has already grown larger than we ever dreamed.
Weβve also seen projects/products/application we never even imagined.
Numbers
- Downloads: 125,000/week, 2.4M total
- Stars: 6,200
- Contributors: 50
- Pull requests: 281
- Commits: 670
The contributor growth is one of the most important aspects here as we have
numerous community members that are familiar with MDX internals.
This allows us to continually improve the project and spread the workload
against an ever growing team of contributors.
Ecosystem
π£ Roadmap
With v1 released we have a roadmap in place that weβll continue working towards
over the next 6 months or so in addition to bug fixes and parsing issues we
might encounter.
- MDXs: #454
- Interleaving: #195
- Global shortcodes: #508
- Stable Vue support: #238
- Blocks: MDX WYSIWYG: blocks/blocks
- MDX playground inspired by AST Explorer: #220
- New splash page: #444
- Showcase page: #414
Vue support
Supporting Vue is an important goal for MDX and is one of the primary reasons
weβve rearchitected MDX to use custom pragma.
Weβre delighted that we now have an alpha version for Vue working.
Weβd love it if anyone from the Vue community wants to give it a try and provide
feedback.
Blocks project
One of the key missing aspects of authoring MDX documents is the editing
experience.
Currently, there isnβt an approachable way to write MDX unless you enjoy working
in a text editor and writing raw Markdown/code.
Weβd like to solve that and have begun work on an MDX βblocks editorβ thatβs a
content-focused WYSIWYG.
Not to mention, weβll be doing all that we can to make sure the editor is as
accessible as it can be from the beginning.
When we have a beta ready we will be open sourcing it and announcing, so stay
tuned.
unified collective
MDX is part of the unified collective, which is an open source ecosystem for
dealing with many sources of content.
unified projects are used all over the web, and it would never be possible
without financial support from our fine sponsors.
π Thanks
Weβd like to say thanks to all our contributors and our happy users.
Special thanks to
@wooorm,
@silvenon,
@timneutkens,
@ChristopherBiscardi,
@jxnblk,
@alexandernanberg,
@jescalan,
@Jarred-Sumner,
@leimonio,
@ticky,
@jamesknelson,
@pshrmn,
@rauchg,
@joelhooks,
@jlengstorf,
@johnlindquist,
@kyleamathews,
@kentcdodds,
@wesbos,
@rosew,
@pedronauck,
@tayiorbeii,
@nickbender,
@ntaylor89,
@mxstbr,
@manovotny,
@xyc,
@filoxo,
@millette,
@hugmanrique,
@johnsherrard,
@sw-yx,
and anyone we may have forgotten.
File: docs/blog/v2.mdx
import {Note} from '../_component/note.jsx'
export const info = {
author: [
{github: 'wooorm', name: 'Titus Wormer'}
],
modified: new Date('2025-01-27'),
published: new Date('2022-02-01')
}
MDX 2
Version 2 of MDX was released after years of hard work, and has many
improvements.
Here are the highlights:
{/* more */}
- π Improved syntax makes it easier to use markdown in JSX
- π§βπ» JavaScript expressions turn
{2 * Math.PI}into {2 * Math.PI} - π New esbuild, Rollup, and Node.js integrations
- βοΈ Any JSX runtime: React, Preact, Vue, Emotion, you name it, theyβre
all supported - π³ Improved AST exposes more info in greater detail
- πββοΈ Compiles at least 25% faster
- π΄ Generated code runs twice as fast (100% faster)
- π Bundle size of
@mdx-js/mdxis more than three times as small
(250% smaller) - π§΅ β¦and much, so much more
Itβs been 4 years since this project was announced.
2Β½ since we released our stable version 1.
Weβre proud to finally release v2!
Letβs dive in!
Contents
- Improvements to the MDX format
- Rollup, esbuild, and other integrations
- Architectural improvements
- TypeScript
- Docs & site
- Breaking changes
- Thanks
Improvements to the MDX format
Weβve spent a lot of time thinking and trying out different ways to improve the
format.
Originally, the format was very close to how markdown, and HTML in markdown,
works.
We found that the old behavior often yielded unexpected results.
In version 2, we shift the format a little bit closer to how JS(X) works.
Take for example this MDX file:
*hi*?
# hi?
<main>
# hi?
</main>In version 1, that was equivalent to the following JSX:
```tsx chrome=no
<>
*hi*?
# hi?
<main>
`# hi?`
</main>
</>
```
In version 2, itβs equivalent to the following JSX:
```tsx chrome=no
<>
*hi*?
<h1>hi?</h1>
<main>
<h1>hi?</h1>
</main>
</>
```We believe itβs more intuitive that markdown βinlinesβ such as emphasis can form
between tags on the same line (first ), βblocksβ such as headings can form if theyβre on their own line (second ), and indentation is allowed
rather than forming code (third ``).
We also added support for JavaScript expressions, take for example:
```mdx path="expressions.mdx"
export const authors = [
{name: 'Jane', email: '[email protected]'},
{name: 'John', github: '@johno'}
]
export const published = new Date('2022-02-01')
Written by: {new Intl.ListFormat('en').format(authors.map(d => d.name))}.
Published on: {new Intl.DateTimeFormat('en', {dateStyle: 'long'}).format(published)}.
```
```tsx path="equivalent.jsx"
<>
Written by: Jane and John.
Published on: February 1, 2022.
</>
```As the format moves a little further from markdown towards JSX, weβve added
support for loading βnormalβ markdown without our syntax extensions.
If youβre using our bundler integration @mdx-js/loader (or @mdx-js/rollup,@mdx-js/esbuild, or @mdx-js/node-loader, see next section), then thatβll
just work: import readme.mdx and itβs seen as the MDX format, importreadme.md and itβs seen as markdown, based on their extensions.
The MDX format is described in Β§ What is MDX?
Rollup, esbuild, and other integrations
When we started out, Babel, webpack, and React were ubiquitous in the JavaScript
ecosystem and we built MDX on them.
For version 2, we worked hard to make them optional.
Theyβre no longer required and MDX can more easily be used with other tools.
On the bundler side, weβve added new integrations: @mdx-js/esbuild for
esbuild (an extremely fast bundler) and @mdx-js/rollup for Rollup (a bundler
thatβs also used in Vite and WMR).
You can even import MDX files directly in Node.js with our new@mdx-js/node-loader.
On the runtime side, we can now compile JSX away to normal JavaScript and
no longer need framework-specific code to glue them together with MDX.
Now any JSX runtime, whether classic or automatic, is supported.
This means MDX can be used with React, Preact, Vue, Emotion, Theme UI, Ink, you
name it, plus anything thatβs yet to be invented!
See Β§ Getting started for a quick start but also in-depth
info on how to integrate MDX with many different tools.
Architectural improvements
To make the syntax of the MDX format better and to allow new integrations and
arbitrary JSX runtimes, weβve rewritten almost everything.
Part of that effort was micromark, which is another story, but it means
weβre fully CommonMark (and optionally GFM) compliant, while also understanding
more about MDX files.
Now we can throw an early error when thereβs a typo and point to exactly where
it happened, instead of a later bundler like webpack complaining about an error
in an intermediate, unrecognizable, and broken string of JavaScript.
It also means that we have a new AST which describes the MDX syntax in more
detail β we even expose the embedded JavaScript.
This detailed AST allows plugins to enhance MDX in powerful new ways.
It also helped solve edge cases where MDX would previously crash.
And it let us drop Babel.
This new architecture results in 25% faster compilation, generated code
that runs twice as fast (100% faster), and that the bundle size of@mdx-js/mdx is more than three times as small (250% smaller).
See ΒΆ Architecture in @mdx-js/mdx for more on how our compiler
works.
See Β§ Extending MDX for several plugins that use the new tree to
enhance MDX, how to use them and other plugins, and how to create plugins.
TypeScript
All @mdx-js/* packages are now fully typed with TypeScript
through JSDoc comments.
That means our APIs are exposed as TypeScript types but also that our projects
are type safe internally.
Weβve published @types/mdx, a types-only package that can be used
with any (community) integration.
You can use it, if youβre importing MDX files, to type those imported
components.
See ΒΆ TypeScript in Β§ Getting started for more on how to use configure
TypeScript.
Docs & site
MDX is used and liked a lot.
Before version 1 we had amassed a total of 2.5m downloads.
Now we hit that number every week.
Our core compiler @mdx-js/mdx is used in 61k projects.
Our GitHub repo has 11.6k stars.
Many people help, often with docs.
85 contributors committed to our repo since version 1.
Weβre grateful for these contributions and all those individual insights,
but over the years it did result in some inconsistencies and duplicated content.
For version 2, we rewrote our docs from beginning to end to tell a consistent
story for new users, folks that do complex AST and compiler stuff, and
anyone in between.
We also made a new website.
Itβs built on MDX of course, unified itself, and React Server Components
(RSC).
While we dogfood the former two as theyβre projects we maintain, and the
latter is extremely experimental, we think compiling things ahead of time and
betting on hybrid models, compared to completely server-side sites or completely
client-side apps, is the smart choice for us and the webβs future.
Our new site is heavily optimized and fast, gorgeous (subjective but hey), has
rich metadata, and scores very well in performance and accessibility review
tools such as Lighthouse and axe.
See Β§ Contribute for more on how to help.
Breaking changes
When youβre ready to migrate, please see the
Version 2 migration guide.
Thanks
Weβd like to say thanks to all our contributors and our happy users.
Special thanks to
John Otander (@johno),
Christian Murphy (@ChristianMurphy),
JounQin (@JounQin),
Jack Bates (@jablko),
Sam Chen (@chenxsan),
Sam Robbins (@samrobbins85),
Remco Haszing (@remcohaszing),
LB (@laurieontech),
Gabriel Kirkley (@gdgkirkley>),
Hung-I Wang (@Gowee),
Ilham Wahabi (@iwgx),
Kaito Sugimoto (@HelloRusk),
Karl Horky (@karlhorky),
Katie Hughes (@glitteringkatie),
Lachlan Campbell (@lachlanjc),
Marcy Sutton (@marcysutton),
Marius Gundersen (@mariusGundersen),
Marius-Remus Mate,
Mark Skelton (@mskelton),
Martin V (@ndresx),
Matija MarohniΔ (@silvenon),
Michael Oliver (@michaeloliverx),
MichaΓ«l De Boey (@MichaelDeBoey),
Muescha (@muescha),
Norviah (@Norviah),
Paul Scanlon (@PaulieScanlon),
Peter Mouland (@peter-mouland),
Prince Wilson (@maxcell),
Rafael Almeida (@rafaelalmeidatk),
Rodrez (@rodrez),
Rongjian Zhang (@pd4d10),
Taeheon Kim (@lonyele),
Tom Parker-Shemilt (@palfrey),
Try Ajitiono (@imballinst),
Yamagishi Kazutoshi (@ykzts),
Yoav Kadosh (@ykadosh),
Yordis Prieto (@Yordis),
Adrian Foong (@adrfoong),
Dan Abramov (@gaearon),
@ihupoo,
@nikhog,
@redallen,
Akshay Kadam (@deadcoder0904),
Ρ ΠΊΠΎΡΠΈΠΊ ΠΏΡΡ-ΠΏΡΡ (@mvasilkov),
Anders D. Johnson (@AndersDJohnson),
Andrew Aylett (@andrewaylett),
Ankeet Maini (@ankeetmaini),
Biswas Nandamuri (@Biswas-N),
Bret (@bcomnes),
Chris Chinchilla (@ChrisChinchilla),
Christopher Biscardi (@ChristopherBiscardi),
Dan Overton (@dan-overton),
Domitrius (@domitriusclark),
Dovi Winberger (@dowi),
Emmie PΓ€ivΓ€rinta (@emmiep),
Eugene Ghanizadeh (@loreanvictor),
and anyone we may have forgotten.
File: docs/blog/v3.mdx
import {Note} from '../_component/note.jsx'
export const info = {
author: [
{github: 'wooorm', name: 'Titus Wormer'}
],
modified: new Date('2025-01-27'),
published: new Date('2023-10-24')
}
MDX 3
Version 3 already!
This major version contains a couple small changes.
For most folks, updating Node.js and plugins is all thatβs needed!
{/* more */}
Contents
Breaking changes
The main breaking change is that Node.js 16 is now the minimum supported
version.
Across the ecosystem there were several small internal breaking changes.
Everythingβs released already.
You can update all plugins now.
If you ran into problems before, it should work now.
We also removed some infrequently used deprecated APIs.
Youβre likely fine but gloss over the v3 migration guide if you
get errors.
Important to note when you use your lesser-known but powerful evaluate, run,
or outputFormat: 'function-body' APIs, please pass the baseUrl option.
That makes sure import.meta.url, import, and export work.
Youβll get a runtime error when those features are used otherwise.
Improvements to the MDX format
Thereβs also a few small improvements to the MDX format, some of which
technically breaking.
Adjacent block JSX and expressions in MDX
We now accept block expressions right next to block JSX tags:
<style>{`
h1 {
color: blue;
}
`}</style>Previously, there was a syntax error, and you had to add a newline between the
angle brackets and the braces.
Await in MDX
We now accept await syntax:
{await Promise.resolve(42)}Most frameworks donβt support promises.
Whether this works depends on that.
Previously, there was a runtime error that await was used in a context where
it wasnβt allowed.
ES2024 in MDX
You can now use modern JavaScript syntax in MDX.
Acorn, used internally, is now instructed to use ES2024.
Miscellaneous
I refactored all the docs.
Updating every use example where needed.
I also wrote a guide on how to inject components from anywhere:
Β§ Injecting components.
The site is a lot faster.
Thereβs a nice improved playground too: try it out! Β».
We also have proper syntax highlighting here, thanks towooorm/markdown-tm-language
and wooorm/starry-night.
The generated JS code is a little cleaner (the JSX pragma comment is removed
and objects are sorted where needed), it also uses spreads instead ofObject.assign, thereβs a 'use strict' added when needed, and theMDXContent is exported immediately.
Thanks
Weβd like to say thanks to all our contributors and our happy users.
Special thanks to
ειδΊδΎ (@BeiyanYunyi),
Christian Murphy (@ChristianMurphy),
JokcyLou (@Jokcy),
MaΓ«l Nison (@arcanis),
Andreas Deininger (@deining),
Remco Haszing (@remcohaszing),
SΓ©bastien Lorber (@slorber),
VΓctor FernΓ‘ndez (@victor23k),
Titus Wormer (@wooorm),
and anyone we may have forgotten.
File: docs/community/about.mdx
import {Note} from '../_component/note.jsx'
export const info = {
author: [
{github: 'wooorm', name: 'Titus Wormer'}
],
modified: new Date('2025-01-27'),
published: new Date('2021-10-06')
}
export const navSortSelf = 4
About
This article explains in short how MDX came to be and why it exists.
It also gives thanks to the people whoβve helped make it and inspired it.
{/* more */}
What is MDX?
MDX is the combination of markdown with JSX.
See Β§ What is MDX? for more info.
Why MDX?
Markdown does not have a syntax for custom components.
MDX solves this.
There are many languages objectively better than markdown, however, markdown is
great because:
- It looks like what it means and is relatively easy to read
- Although images are confusing, most stuff is relatively simple to write
- Itβs loose and ambiguous: it may not work but you wonβt get an error (great
for someone posting a comment to a forum if they forgot an asterisk)
Markdown does have a way to extend it, HTML, but that has drawbacks:
- HTML in markdown is naΓ―ve, how itβs parsed sometimes doesnβt make sense
- HTML is unsafe by default, so itβs sometimes (partially) unsupported
- HTML and markdown donβt mix well, resulting in confusing rules such as
blank lines ormarkdown="1"attributes - HTML is coupled with browsers, markdown is useful for other things too
The frontend world has an alternative to HTML: JSX.
JSX is great, amongst other things, because:
- It has a relatively familiar syntax (like XML)
- Itβs agnostic to semantics and intended for compilers (can have any
domain-specific meaning) - Itβs strict and unambiguous (great if an author forgot a slash somewhere, as
theyβll get an error early, instead of a book going to print with broken
stuff in it)
Who governs MDX?
The project is governed by the
unified collective.
Who created MDX?
The idea of combining markdown, JavaScript, and JSX was a
collaborative effort by
Guillermo Rauch (@rauchg),
James K. Nelson (@jamesknelson),
John Otander (@johno),
Tim Neutkens (@timneutkens),
Brent Jackson (@jxnblk),
Jessica Stokes (@ticky), and more.
While everyone above was key to MDX, we want to stress the involvement of
John Otander (@johno).
John wrote most of the code for the first alpha and later stable version 1 of
this project!
Who designed the logo?
Logo designs were created by Evil Rabbit of Vercel.
What projects inspired MDX?
The following projects, languages, and articles helped shape MDX either in
implementation or inspiration.
The markdown and JSX languages inspired MDX.
Markdown was created by John Gruber (@gruber).
CommonMark, the most popular markdown variant, by John McFarlane
(@jgm) et al.
JSX was created by Sebastian MarkbΓ₯ge (@sebmarkbage) et
al. at Facebook, Inc.
The @mdx-js/* projects currently make heavy use of unified (specifically
micromark, remark and rehype) and Acorn.
unified, remark, rehype, and related tools were created by Titus Wormer
(@wooorm) et al.
Acorn by Marijn Haverbeke (@marijnh) et al.
The following projects inspired @mdx-js/* originally:
{/* Note: please keep the original project names intact: */}
jamesknelson/mdxcticky/markdown-component-loaderthreepointone/markdown-in-jsfazouane-marouane/remark-jsxmapbox/remark-reactrx-ts/eslint-mdx
The following articles inspired @mdx-js/* originally:
File: docs/community/contribute.mdx
import {Note} from '../_component/note.jsx'
export const info = {
author: [
{github: 'wooorm', name: 'Titus Wormer'}
],
modified: new Date('2025-01-27'),
published: new Date('2018-11-04')
}
export const navSortSelf = 2
Contribute
This article explains how to contribute to MDX.
Please read through the following guidelines.
{/* more */}
Contributions
Thereβs several ways to contribute, not just by writing code.
If you have questions, see Β§ Support.
If you can provide financial support, see Β§ Sponsor.
Improve docs
As a user youβre perfect for helping us improve our docs.
Typo corrections, error fixes, better explanations, new examples, etcetera.
All MDX docs live in docs/.
You can run the docs locally, see ΒΆ Site below.
Improve issues
Some issues lack information, arenβt reproducible, or are just incorrect.
You can help by trying to make them easier to resolve.
Existing issues might benefit from your unique experience or opinions.
Write code
Code contributions are very welcome.
Itβs probably a good idea to first post a question or open an issue to report a
bug or suggest a new feature before creating a pull request.
Submitting an issue
- The issue tracker is for issues.
Use discussions for support - Search the issue tracker (including closed issues) before opening a new
issue - Ensure youβre using the latest version of our packages
- Use a clear and descriptive title
- Include as much information as possible: steps to reproduce the issue,
error message, version, operating system, etcetera - The more time you put into an issue, the better we will be able to help you
- The best issue report is a failing test proving it
Submitting a pull request
- See ΒΆ Project below for info on how the project is structured,
how to test, and how to build the site - Non-trivial changes are often best discussed in an issue first, to prevent
you from doing unnecessary work - For ambitious tasks, you should try to get your work in front of the
community for feedback as soon as possible - New features should be accompanied by tests and documentation
- Donβt include unrelated changes
- Test before submitting code by running
npm test - Write a convincing description of why we should land your pull request:
itβs your job to convince us
Project
Structure
MDX is a monorepo.
All packages are in packages/.
Documentation is in docs/.
Tests
To run the tests, first do npm install, then do npm test.
This ensures everything is okay, from code style to unit tests to types.
Site
To build the site, first do npm install, then do npm run docs.
This produces the website in public/.
Release
To release a new version, do:
- update
versions of packages with a patch, minor, or major (make sure to
update dependency ranges on monorepo packages when needed):shnpm version minor --workspaces --no-git-tag-version - commit and tag using the version (without
v) as the message:shgit commit --all --message 1.2.3 && git tag 1.2.3 && git push && git push --tags - release to the npm registry:sh
npm publish --workspaces - add a changelog entry for the release on GitHub:sh
open https://github.com/mdx-js/mdx/releases