Skip to navigation
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:

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

# {title}

Can be used like so:

example.js
import * as Post from './example.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:

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

# Hi, World!

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

example.js
import {read} from 'to-vfile'
import {matter} from 'vfile-matter'

const file = await read('example.mdx')
matter(file)

console.log(file.data.matter)

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 {compile} from '@mdx-js/mdx'
import remarkFrontmatter from 'remark-frontmatter'

const file = await compile(await fs.readFile('example.mdx'), {
  remarkPlugins: [remarkFrontmatter]
})

console.log(file)

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

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

# {title}

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

That plugin, like all remark plugins, can be passed as remarkPlugins in ProcessorOptions. More info on plugins is available in § Extending MDX