remark’s power comes from its plugins. Every feature beyond bare CommonMark parsing — GitHub Flavored Markdown tables, a generated table of contents, lint checks, math notation, MDX support — is delivered by a plugin. Understanding how plugins are structured lets you use existing ones effectively and write your own when you need something custom.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/remarkjs/remark/llms.txt
Use this file to discover all available pages before exploring further.
What is a plugin?
A plugin is a function passed to.use() on a unified processor. It receives an options object (if you pass one) and returns a transformer function. That transformer is called during the transform phase with the parsed mdast tree and the vfile, before the stringifier runs.
.use() call is the same from the outside.
Two kinds of plugins
Syntax extensions
Add new parsing and/or serialization support. These plugins hook into micromark (the underlying parser) to teach remark about new syntax — things like GFM tables, math blocks, or frontmatter. Examples:
remark-gfm, remark-math, remark-frontmatter, remark-mdx.Transformers
Inspect or change the mdast tree after parsing. These are plain functions that receive the tree and the vfile and can read, mutate, or replace any part of the tree. Examples:
remark-lint, remark-toc, remark-rehype.remark-gfm extends the parser to recognize GFM syntax and extends the serializer to emit it correctly.
The plugin lifecycle
Parse
remark-parse (or a custom parser) converts the markdown source string into an mdast tree. Syntax-extension plugins registered with .use() before parsing add new token types to micromark so novel constructs are recognized.Transform
Each transformer plugin runs in the order it was registered. Each one receives the same tree (potentially mutated by earlier plugins) and the vfile. A plugin can walk the tree, add or remove nodes, attach messages to the vfile, or even replace the tree root entirely.
Writing your first plugin
The example below is taken directly from the remark source. It increases the depth of every heading in a document by one — turning every# h1 into ## h2, every ## h2 into ### h3, and so on.
- The outer function
myRemarkPluginToIncreaseHeadingsis the plugin. It could accept anoptionsargument if needed. - It returns an inner function — the transformer — which receives the
tree. visitfromunist-util-visitwalks every node in the tree depth-first.- Mutating
node.depthis all that is needed; the tree is passed by reference.
If your transformer needs to do async work (for example, fetching data for each link), return a
Promise from the transformer function. unified will await it before moving to the next plugin.Plugins with options
Plugins accept options via a second argument to.use(). The outer function receives those options before returning the transformer:
Extending the parser and serializer
Syntax-extension plugins don’t just return a transformer — they also register low-level extensions on the unified processor usingprocessor.data(). The three keys used by remark are:
micromarkExtensions— extensions passed to micromark, the underlying tokenizer. These teach the parser to recognize new syntax tokens (used byremark-parse).fromMarkdownExtensions— extensions passed tomdast-util-from-markdown. These describe how to build mdast nodes from the new tokens (used byremark-parse).toMarkdownExtensions— extensions passed tomdast-util-to-markdown. These describe how to serialize the new node types back to markdown text (used byremark-stringify).
remark-gfm registers on all three keys so that GFM syntax is correctly parsed, represented in the tree, and re-serialized. As a plugin author you normally don’t call data() directly — you use an existing syntax-extension package and follow its documentation. But knowing these keys helps when debugging unexpected parsing behavior or building your own micromark integration.
Popular plugins
The remark ecosystem has over 150 plugins. Below are some of the most widely used:remark-gfm
Adds full GitHub Flavored Markdown support: autolink literals, footnotes, strikethrough, tables, and tasklists.
remark-lint
Checks markdown for code style consistency and adherence to best practices. Comes with dozens of configurable rules and preset packages.
remark-toc
Generates a table of contents by scanning headings and inserting a linked list under a designated heading (e.g.
## Contents).remark-rehype
Converts the mdast tree into a hast (HTML AST) tree, bridging the remark and rehype ecosystems so you can apply HTML-level plugins before serializing.
remark-frontmatter
Adds support for YAML, TOML, and other frontmatter formats. The frontmatter block is parsed as its own node type rather than treated as raw content.
remark-math
Adds syntax for inline math (
$…$) and math blocks ($$…$$), producing new node types that rehype plugins can render with KaTeX or MathJax.remark-mdx
Adds full MDX support: JSX, expressions, and ESM import/export statements. The foundation of the MDX ecosystem.
remark-directive
Introduces a generic directive syntax (
:name[content]{attr}) that can be used to build custom extensions without writing a micromark integration from scratch.Finding more plugins
Three reliable ways to discover remark plugins:- awesome-remark — a curated selection of the most useful and well-maintained projects.
- List of plugins — the comprehensive list in the remark repository, annotated with compatibility status.
remark-pluginGitHub topic — every public repo tagged with theremark-plugintopic.
Naming conventions
If you publish your own plugin, follow the naming conventions used by the ecosystem:- Prefix with
remark-for plugins that work withremark().use()— for example,remark-my-feature. - Use
mdast-util-for utilities that work directly with mdast trees without being unified plugins. - Use
unist-util-for utilities that work with any unist-compatible tree. - Add the
remark-plugintopic to your GitHub repository and add akeywordsentry inpackage.jsonso others can find your work.