remark-frontmatter, remark-gfm, remark-html, remark-mdx, and remark-parse are plugins or core components in the Unified ecosystem (specifically Remark) that enable advanced Markdown processing. remark-parse is the foundational parser that converts Markdown strings into an abstract syntax tree (AST). The other packages are plugins that extend this AST: remark-frontmatter handles YAML/TOML frontmatter, remark-gfm adds GitHub Flavored Markdown support (tables, task lists, etc.), remark-html transforms the AST into HTML strings, and remark-mdx enables parsing and processing of MDX (Markdown + JSX). Together, they allow developers to build customizable, powerful Markdown-to-HTML pipelines with support for metadata, extended syntax, and embedded components.
When building modern content pipelines — whether for blogs, documentation, or CMS backends — developers often reach for the Unified ecosystem, where Remark handles Markdown processing. The packages remark-parse, remark-frontmatter, remark-gfm, remark-mdx, and remark-html each play distinct roles in this pipeline. Understanding how they fit together — and when to use which — is key to building efficient, maintainable systems.
Every Remark pipeline follows a simple flow:
remark-parse)remark-gfm, remark-frontmatter, remark-mdx)remark-html for HTML strings)Let’s see how each package fits into this flow.
remark-parse: The FoundationThis is the only parser in the list. Without it, you can’t process Markdown at all in a Remark pipeline. It converts a string like # Hello into a structured tree that other tools can modify.
import { unified } from 'unified';
import remarkParse from 'remark-parse';
const processor = unified().use(remarkParse);
const ast = processor.parse('# Hello');
// Returns a root node with a heading child
⚠️ You must use
remark-parse(or a compatible parser) before applying any Remark plugins. None of the other packages in this comparison can parse raw Markdown on their own.
remark-html: The Output GeneratorOnce you have an AST, remark-html turns it into a plain HTML string. It’s a compiler, not a transformer — it doesn’t modify the AST; it consumes it.
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkHtml from 'remark-html';
const processor = unified()
.use(remarkParse)
.use(remarkHtml);
const html = processor.processSync('# Hello').toString();
// Returns '<h1>Hello</h1>'
Note: remark-html works after all transformations. If you’ve added GFM tables or MDX components, remark-html won’t know how to render them unless you’ve first converted those nodes to standard HTML-compatible ones (usually via remark-rehype). But for basic Markdown, it’s sufficient.
remark-frontmatter, remark-gfm, remark-mdx: AST TransformersThese three modify the AST during processing. They must come after remark-parse and before serialization.
remark-frontmatter: Extracting MetadataHandles frontmatter blocks like:
---
title: My Post
date: 2024-01-01
---
# Content
Usage:
import remarkFrontmatter from 'remark-frontmatter';
const processor = unified()
.use(remarkParse)
.use(remarkFrontmatter, ['yaml', 'toml']); // supports multiple formats
const ast = processor.parse('---\ntitle: Test\n---\n# Hi');
// AST now includes a `yaml` node at the top
Without this plugin, the --- block would be parsed as a thematic break (horizontal rule), corrupting your metadata.
remark-gfm: Adding GitHub Flavored MarkdownEnables syntax like tables, task lists, and autolinks:
| Name | Age |
|------|-----|
| Alice| 30 |
- [x] Done
- [ ] Todo
Visit https://example.com
Usage:
import remarkGfm from 'remark-gfm';
const processor = unified()
.use(remarkParse)
.use(remarkGfm);
const ast = processor.parse('| A | B |\n|---|---|\n| 1 | 2 |');
// AST includes a `table` node
Without remark-gfm, that table would be parsed as plain paragraphs.
remark-mdx: Embedding JSX in MarkdownAllows mixing React-like components in Markdown:
# Hello
Here is a chart:
<BarChart data={data} />
Usage:
import remarkMdx from 'remark-mdx';
const processor = unified()
.use(remarkParse)
.use(remarkMdx);
const ast = processor.parse('# Hi\n\n<MyComponent />');
// AST includes an `mdxJsxTextElement` node
🔒 Warning: MDX execution can introduce security risks (e.g., arbitrary code injection) if used with untrusted input. Always sanitize or restrict component usage in public-facing apps.
The sequence of plugins affects correctness. Here’s a typical full pipeline for GFM + frontmatter:
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkFrontmatter from 'remark-frontmatter';
import remarkGfm from 'remark-gfm';
import remarkHtml from 'remark-html';
const processor = unified()
.use(remarkParse)
.use(remarkFrontmatter, ['yaml'])
.use(remarkGfm)
.use(remarkHtml);
const result = processor.processSync(`---
title: Demo
---
- [x] Task
| A | B |
|---|---|`);
If you put remark-html before remark-gfm, tables won’t render — because the HTML compiler runs before the GFM syntax is recognized.
rehype-sanitize.remark-mdx does not execute JSX — it only parses it into an AST. To render components, you need additional tooling (e.g., @mdx-js/react).remark-html cannot render MDX components — it outputs literal <MyComponent /> as a string. For component-aware rendering, convert to React via remark-rehype + rehype-react.| Use Case | Required Packages |
|---|---|
| Basic Markdown → HTML | remark-parse + remark-html |
| Markdown with YAML metadata | Add remark-frontmatter |
| GitHub-style Markdown | Add remark-gfm |
| Interactive docs with components | Replace remark-html with MDX-aware pipeline (remark-mdx → remark-rehype → rehype-react) |
Start minimal: always begin with remark-parse and remark-html. Then layer in transformers only as needed:
remark-frontmatterremark-gfmremark-html with an MDX pipeline using remark-mdxAvoid over-engineering. If you don’t use tables or task lists, skip remark-gfm. If you don’t have frontmatter, skip remark-frontmatter. Each plugin adds maintenance surface and potential edge cases.
By understanding these roles — parser, transformers, serializer — you’ll build cleaner, more predictable Markdown processing systems.
Choose remark-parse whenever you start processing Markdown in a Unified pipeline — it’s the required first step to turn raw Markdown text into a syntax tree that other plugins can transform. Never skip it unless you’re working directly with an existing AST. It’s lightweight and focused solely on parsing, so always include it in any Remark-based workflow.
Choose remark-gfm when you need to support GitHub-style Markdown features such as tables, strikethrough, task lists, or autolinks. This is essential for user-generated content from GitHub or tools that expect GFM compatibility. Don’t use it if you only need standard CommonMark compliance, as it introduces extra syntax rules that may not be needed.
Choose remark-mdx when you need to process MDX — Markdown that supports embedded JSX components. This is critical for documentation sites, interactive blogs, or design systems built with frameworks like Next.js or Gatsby. Only use it if you actually require component interpolation; otherwise, stick with standard Markdown plugins to avoid complexity and security considerations.
Choose remark-frontmatter when your Markdown files include metadata blocks (like YAML or TOML) at the top — common in static site generators like Jekyll or Hugo. It safely extracts this data into the AST without affecting the rest of the document. Avoid it if your content doesn’t use frontmatter, as it adds unnecessary parsing overhead.
Choose remark-html when your goal is to convert a Markdown AST into a plain HTML string for rendering in browsers or email templates. It’s the standard serializer after parsing and transforming Markdown. Avoid using it if you’re targeting React (use rehype-react instead) or another output format like JSON or PDF.
remark plugin to add support for parsing from markdown.
This package is a unified (remark) plugin that defines how to take markdown as input and turn it into a syntax tree.
See the monorepo readme for info on what the remark ecosystem is.
This plugin adds support to unified for parsing markdown.
If you also need to serialize markdown, you can alternatively use
remark, which combines unified, this plugin, and
remark-stringify.
If you just want to turn markdown into HTML (with maybe a few extensions),
we recommend micromark instead.
If you don’t use plugins and want to access the syntax tree, you can directly
use mdast-util-from-markdown.
remark focusses on making it easier to transform content by abstracting these
internals away.
You can combine this plugin with other plugins to add syntax extensions.
Notable examples that deeply integrate with it are
remark-gfm,
remark-mdx,
remark-frontmatter,
remark-math, and
remark-directive.
You can also use any other remark plugin after remark-parse.
This package is ESM only. In Node.js (version 16+), install with npm:
npm install remark-parse
In Deno with esm.sh:
import remarkParse from 'https://esm.sh/remark-parse@11'
In browsers with esm.sh:
<script type="module">
import remarkParse from 'https://esm.sh/remark-parse@11?bundle'
</script>
Say we have the following module example.js:
import rehypeStringify from 'rehype-stringify'
import remarkGfm from 'remark-gfm'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import {unified} from 'unified'
const doc = `
# Mercury
**Mercury** is the first planet from the [Sun](https://en.wikipedia.org/wiki/Sun)
and the smallest planet in the Solar System.
`
const file = await unified()
.use(remarkParse)
.use(remarkGfm)
.use(remarkRehype)
.use(rehypeStringify)
.process(doc)
console.log(String(file))
…then running node example.js yields:
<h1>Mercury</h1>
<p><strong>Mercury</strong> is the first planet from the <a href="https://en.wikipedia.org/wiki/Sun">Sun</a>
and the smallest planet in the Solar System.</p>
This package exports no identifiers.
The default export is remarkParse.
unified().use(remarkParse)Add support for parsing from markdown.
There are no parameters.
Nothing (undefined).
We support CommonMark by default. Non-standard markdown extensions can be enabled with plugins.
This example shows how to support GFM features (autolink literals, footnotes, strikethrough, tables, tasklists) and frontmatter (YAML):
import rehypeStringify from 'rehype-stringify'
import remarkFrontmatter from 'remark-frontmatter'
import remarkGfm from 'remark-gfm'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import {unified} from 'unified'
const doc = `---
layout: solar-system
---
# Hi ~~Mars~~Venus!
`
const file = await unified()
.use(remarkParse)
.use(remarkFrontmatter)
.use(remarkGfm)
.use(remarkRehype)
.use(rehypeStringify)
.process(doc)
console.log(String(file))
Yields:
<h1>Hi <del>Mars</del>Venus!</h1>
Man pages (short for manual pages) are a way to document CLIs (example: type
man git-log in your terminal).
They use an old markup format called roff.
There’s a remark plugin, remark-man, that can serialize as
roff.
This example shows how to turn markdown into man pages by using unified with
remark-parse and remark-man:
import remarkMan from 'remark-man'
import remarkParse from 'remark-parse'
import {unified} from 'unified'
const doc = `
# titan(7) -- largest moon of saturn
Titan is the largest moon…
`
const file = await unified().use(remarkParse).use(remarkMan).process(doc)
console.log(String(file))
Yields:
.TH "TITAN" "7" "September 2023" "" ""
.SH "NAME"
\fBtitan\fR - largest moon of saturn
.P
Titan is the largest moon…
Markdown is parsed according to CommonMark. Other plugins can add support for syntax extensions. If you’re interested in extending markdown, more information is available in micromark’s readme.
The syntax tree used in remark is mdast.
This package is fully typed with TypeScript.
It exports the additional type Options (which is currently empty).
Projects maintained by the unified collective are compatible with maintained versions of Node.js.
When we cut a new major release, we drop support for unmaintained versions of
Node.
This means we try to keep the current release line, remark-parse@^11,
compatible with Node.js 16.
As markdown can be turned into HTML and improper use of HTML can open you up to
cross-site scripting (XSS) attacks, use of remark can be unsafe.
When going to HTML, you will combine remark with rehype, in which case
you should use rehype-sanitize.
Use of remark plugins could also open you up to other attacks. Carefully assess each plugin and the risks involved in using them.
For info on how to submit a report, see our security policy.
See contributing.md in remarkjs/.github for ways
to get started.
See support.md for ways to get help.
Join us in Discussions to chat with the community and contributors.
This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.
Support this effort and give back by sponsoring on OpenCollective!
|
Vercel |
Motif |
HashiCorp |
GitBook |
Gatsby | |||||
Netlify
|
Coinbase |
ThemeIsle |
Expo |
Boost Note
|
Markdown Space
|
Holloway | |||
|
You? | |||||||||