Skip to navigation
1-2 minutes read
By Titus Wormer

Frontmatter

This guide explores how to support YAML frontmatter in MDX. MDX supports standard markdown syntax (CommonMark). That means frontmatter is not supported by default.

MDX comes with a powerful and dynamic alternative to frontmatter, namely ESM (import/export). These exports:

post.mdx
export const name = 'World'
export const title = 'Hi, ' + name + '!'

# {title}

Can be used like so:

example.js
import * as Post from './post.mdx' // Assumes an integration is used to compile MDX -> JS.

console.log(Post.title) // Prints 'Hi, World!'

You might prefer frontmatter though, as it lets you define data that can be extracted from the file system before compiling. Say our MDX with frontmatter looked like this:

post.mdx
---
title: Hi, World!
---

# Hi, World!

Then without compiling or evaluating the metadata can be accessed like so:

example.js
import fs from 'node:fs/promises'
import yaml from 'js-yaml'

console.log(yaml.loadAll(await fs.readFile('post.mdx'))[0])
// Prints `{title: 'Hi, World!'}`

Our compiler, @mdx-js/mdx, doesn’t understand YAML frontmatter by default but it can be enabled by using a remark plugin, remark-frontmatter:

example.js
import fs from 'node:fs/promises'
import remarkFrontmatter from 'remark-frontmatter'
import {compile} from '@mdx-js/mdx'

console.log(
  await compile(await fs.readFile('post.mdx'), {
    remarkPlugins: [remarkFrontmatter]
  })
)

Now it “works”. The frontmatter is ignored. But the data embedded in the frontmatter isn’t available from inside the MDX. What if we wanted that too? Like so:

post.mdx
---
title: Hi, World!
---

# {title}

That’s exactly what the remark plugin remark-mdx-frontmatter does.

remark plugins can be passed in options.remarkPlugins. More info on plugins is available in § Extending MDX