Skip to content

MDX for Beginners

The MDX syntax combines markdown with JSX. This gives us something along the lines of literate programming. It also gives us an odd mix of two languages: markdown is whitespace sensitive and forgiving (what you type may not exactly work but it won’t crash) whereas JavaScript is whitespace insensitive and unforgiving (it does crash on typos).

The crash course walks you through combination of these two worlds to create more engaging documentation, blog posts, or whatever you’re working on.

To write and enjoy MDX, you should be familiar with both markdown and JavaScript (specifically JSX).

Markdown 101

Markdown often feels more natural to type than HTML or JSX for common things like emphasis or headings. Following Markdown cheat sheet provides a quick overview of all the Markdown syntax elements.

It can’t cover every edge case, so if you need more information about any of these elements, refer to the reference guides for basic syntax and extended syntax.

Basic Syntax

These are the elements outlined in John Gruber’s original design document. All Markdown applications support these elements.

ElementMarkdown Syntax
Heading
# H1
## H2
### H3
Bold
**bold text**
Italic
*italicized text*
Blockquote
> blockquote
Ordered List
1. First item
2. Second item
3. Third item
Unordered List
- First item
- Second item
- Third item
Code
`code`
Horizontal Rule
---
Link
[ChaiDocs](https://docs.chaicode.com)
Image
![chai mascot](chai.png)

Extended Syntax

These elements extend the basic syntax by adding additional features. Not all Markdown applications support these elements.

ElementMarkdown Syntax
Table
| Syntax | Description |
| ----------- | ----------- |
| Header | Title |
| Paragraph | Text |
Fenced Code Block
```json
{
"firstName": "John",
"lastName": "Smith",
"age": 25,
}
```
Footnote
Here's a sentence with a footnote. [^1]
[^1]: This is the footnote.
Heading ID
### My Great Heading {#custom-id}
Definition List
term
: definition
Strikethrough
~~The world is flat.~~
Task List
- [x] Write the press release<br></br>
- [ ] Update the website<br></br>
- [ ] Contact the media

Emoji (see also Copying and Pasting Emoji)

That is so funny! :joy:
Subscript
H~2~O
Superscript
X^2^

Deviations from Markdown

MDX adds constructs to Markdown but also prohibits certain normal Markdown constructs.

HTML

Whether block or inline, HTML in Markdown is not supported.

Character data, processing instructions, declarations, and comments are not supported at all. Instead of HTML elements, use JSX elements.

Incorrect:

# Hello, <span style=color:red>world</span>!
<!--To do: add message-->
<img>

Correct:

# Hello, <span style='color:red'>world</span>!
<img />

Indented code

Indentation to create code blocks is not supported. Instead, use fenced code blocks.

The reason for this change is so that elements can be indented.

Incorrect:

console.log(1)

Correct:

```js
console.log(1)
```

Autolinks are not supported. Instead, use links or references.

The reason for this change is because whether something is an element (whether HTML or JSX) or an autolink is ambiguous (Markdown normally treats <svg:rect>, <xml:lang/>, or <svg:circle{...props}> as links).

Incorrect:

See <https://example.com> for more information

Correct:

See [example.com](https://example.com) for more information.

Errors

Whereas all Markdown is valid, incorrect MDX will crash.

JSX

More practically MDX can be explained as a format that combines markdown with JSX and looks as follows:

# Hello, world!
<div className="note">
> Some notable things in a block quote!
</div>

The heading and block quote are markdown, while those HTML-like tags are JSX. Markdown often feels more natural to type than HTML or JSX for common things like emphasis or headings. JSX is an extension to JavaScript that looks like HTML but makes it convenient to use components (reusable things).

This example uses className on the <div>. That’s because it was written for React and React expects classes that way. Other frameworks, such as Vue and Preact, expect classes to be defined differently, so note that there are some differences in how JSX has to be authored depending on what tools it’s used with.

Expressions

MDX also supports JavaScript expressions inside curly braces:

Two 🍰 is: {Math.PI * 2}

Expressions can contain whole JavaScript programs as long as they’re (wrapped in) an expression that evaluates to something that can be rendered. You can use an IIFE like so:

{(() => {
const guess = Math.random()
return guess > 0.5;
})()}

Expressions can be empty or contain just a comment:

{/* A comment! */}

ESM

MDX supports import and export statements from JavaScript as well. These ESM features can be used within MDX to define things:

import {Chart} from './chart.ts'
import population from './population.ts'
export const pi = 3.14
<Chart data={population} label={'Something with ' + pi} />

Deviations from JSX

MDX removes certain constructs from JSX, because JSX is typically mixed with JavaScript whereas MDX is usable without it.

Comments

JavaScript comments in JSX are not supported.

Incorrect:

<hi/*comment!*//>
<hello// comment!
/>

Correct:

<hi/>
<hello
/>

Element or fragment attribute values

JSX elements or JSX fragments as attribute values are not supported. The reason for this change is that it would be confusing whether Markdown would work.

Incorrect:

<welcome name=<>Venus</> />
<welcome name=<span>Pluto</span> />

Correct:

<welcome name='Mars' />

Common MDX gotchas

Markdown first looks for blocks (such as a heading) and only later looks for spans (such as emphasis) in those blocks.

This becomes a problem typically in the two cases listed below. However, as MDX has parse errors, parsing will crash, and an error will be presented.

Blank lines in JSX spans

Incorrect:

The plot for the movie was, <span>wait for it…
…that she didn’t die!</span>

Correct:

The plot for the movie was, <span>wait for it…
…that she didn’t die!</span>

GREATER THAN (>) seen as block quote

Incorrect:

Here’s a cute photo of my cat: <Image
alt='Photo of Lilo sitting in a tiny box'
src='lilo.png'
/
>

Correct:

Here’s a cute photo of my cat: <Image alt='Photo of Lilo sitting in a tiny box' src='lilo.png' />

Or as a block (GREATER THAN (>) is fine in JSX blocks):

Here’s a cute photo of my cat:
<Image
alt='Photo of Lilo sitting in a tiny box'
src='lilo.png'
/
>

Now that you’re familiar with Markdown and JSX (MDX), let’s see it in action in our component library.

Start your journey with ChaiCode

All of our courses are available on chaicode.com. Feel free to check them out.