# unified: a processor for content as syntax trees

> unified is the core package behind remark, rehype and retext. It wires a parser, a list of transformer plugins and a compiler into one processor, and it is only worth adopting directly when you work across more than one content format.

**unifiedjs/unified** — Parse, inspect, transform, and serialize content with syntax trees

- Repository: https://github.com/unifiedjs/unified
- Website: https://unifiedjs.com
- Stars: 5,037 · Forks: 130
- Language: JavaScript
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/unifiedjs-unified

## The problem unified exists to solve

Most content tooling hard-codes one format. A markdown library parses markdown and returns HTML; an HTML minifier takes HTML and returns HTML. Compose two of them and you end up gluing strings together, which breaks the moment either side changes its output.

unified replaces that with a single abstraction: content goes in as text, comes out as text, and everything in between is a unist syntax tree that plugins can read and rewrite. The core package itself does almost nothing. According to the readme, on its own the root processor does not work and must be configured with plugins.

The audience is narrow and specific. If you are already inside MDX, Gatsby or Docusaurus, the readme notes you are using unified already and can add plugins without installing it yourself. The people who install the core package are those building the pipeline: a site generator, a linter over prose, a format converter, or a Prettier-like tool. The readme puts the split plainly: for one kind of content use that ecosystem's package, such as remark for markdown; when you deal with different kinds of content, use unified itself and pick the plugins you need.

## Parser, transformers, compiler: the actual data flow

A processor moves a document through three stages. A parser turns text into a syntax tree. Transformers, the plugins added with use(), inspect or modify that tree. A compiler turns the tree back into text. The readme draws this as input into parser, tree into compiler, output, with transformers hanging off the tree in the middle. Calling process() runs all three; parse(), run() and stringify() expose the stages individually.

Metadata does not live on the tree. It lives in a vfile, which the readme describes as the format that stores data, metadata and messages about files for unified and plugins. That is how a plugin reports a problem without throwing: it attaches a message to the file, and a reporter such as vfile-reporter prints it separately from the output.

Processors are immutable in one direction. The readme states that creating a processor from another one copies its configuration, and configuring the descendant later does not affect the ancestor. Processors exported from a module are frozen for exactly this reason: configuring them in place would change behaviour for every consumer of that module, so they must be called to produce a new processor first. This is a small design decision with a large consequence for library authors, and it is the part most often missed on a first read.

## Installing unified and running a first markdown-to-HTML pass

The package is ESM only and needs Node.js 16 or newer. The readme gives npm as the install path:

```bash
npm install unified
```

There are also browser and Deno entry points through esm.sh, with the readme showing `https://esm.sh/unified@11` for Deno and a module script tag for browsers.

A first real use means adding the plugins that do the work. The readme's own example parses markdown, converts the tree to HTML, wraps it in a document, formats it, and serializes it:

```js
import rehypeDocument from 'rehype-document'
import rehypeFormat from 'rehype-format'
import rehypeStringify from 'rehype-stringify'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import {unified} from 'unified'

const file = await unified()
  .use(remarkParse)
  .use(remarkRehype)
  .use(rehypeDocument, {title: 'Hello'})
  .use(rehypeFormat)
  .use(rehypeStringify)
  .process('# Hello world!')
```

Every plugin in that chain is a separate npm package, so the install line in the readme is only the start. After process() resolves, `String(file)` gives the compiled HTML and `file` also carries any messages the plugins recorded. The readme shows vfile-reporter being used to print those messages to stderr, yielding `no issues found` when nothing was flagged. Note the order: remark plugins run before rehype plugins, because each plugin registers against the tree type it understands.

## Where unified is the wrong tool

The dependency list is deliberately thin, but the plugin list is not. A working markdown-to-HTML pipeline needs remark-parse, remark-rehype, rehype-stringify and usually rehype-format, each versioned and maintained on its own schedule. If you need one fixed conversion and nothing more, a single-purpose markdown library is less surface area to track.

ESM only is a real constraint, not a footnote. The readme states it directly. A CommonJS codebase on an older Node version cannot import unified without a loader or a build step, and some plugins in the wider ecosystem may lag on the same requirement.

The plugin model also assumes you are comfortable with syntax trees. A transformer receives a tree and a file and is expected to walk and mutate nodes. If your actual task is string substitution or template filling, building a unist walker to do it is more machinery than the problem deserves.

Finally, unified does not validate your content. It moves data between representations. A plugin can attach a message to the vfile, but nothing in the core enforces a schema or fails a build on a malformed tree.

## How unified differs from remark and from a standalone markdown parser

remark is the obvious comparison, and the readme makes the boundary explicit: remark is the ecosystem for markdown, unified is the core. remark itself is built on unified, so choosing remark is not choosing a different architecture, it is choosing a preconfigured entry point for one format.

The practical difference shows up when a second format enters. With remark alone you get markdown in and markdown out. With unified you can parse markdown, transform the tree, convert it to HTML with remark-rehype, and compile with rehype-stringify, all in one processor, because the tree types are designed to connect. The readme states that the remark, rehype and retext ecosystems can be connected together, and that is the capability the core package exists to provide.

Against a standalone markdown-to-HTML parser, the difference is where customisation happens. A standalone parser typically exposes options and maybe an extension hook. unified exposes the tree, so a plugin can add a node type, rewrite an existing one, or read the tree and report a problem without touching the compiler at all.

## Maintenance, releases and the MIT licence

The repository is not archived, and the last push was on 2026-04-29. The most recent release listed is 11.0.5 from 2024-06-19, preceded by 11.0.4 in October 2023 and 11.0.3 in September 2023. The pattern is a stable core with infrequent releases, which fits a package whose job is to define an interface rather than to ship features. The changelog lives in changelog.md at the repository root, so upgrade notes are in the repository rather than only in release pages.

Upgrade cost is mostly about the plugins, not the core. A major bump in unified can require matching majors across remark, rehype and the individual plugins you use, and the readme does not document a migration path for that. Budget for reading the changelog of each plugin in your chain, not just this one.

The licence is MIT, stated in package.json and present as a license file at the repository root. MIT is permissive and imposes no copyleft obligation on your own code. That is a statement about the licence text, not legal advice; if your organisation has a licence review process, run the package and its plugin dependencies through it.

## Conclusion

Adopt unified directly when your pipeline crosses content formats, for example markdown in and HTML out, because that is where the plugin ecosystem pays off. If you only ever touch markdown, install remark instead and skip the extra layer. Before committing, check that every plugin you need is ESM and works on Node 16 or newer, and read the plugin's own readme for the options it accepts, since the unified readme documents the API surface rather than individual plugins.

## FAQ

### What is unified and what does it actually do?

unified is an interface for processing content with syntax trees. A parser turns text into a tree, plugins inspect and modify that tree, and a compiler turns it back into text. On its own the root processor does not work and must be configured with plugins.

### Should I install unified or remark for a markdown project?

The readme says that when you deal with one type of content such as markdown, you can use the main package of that ecosystem instead, so remark. Use unified itself when you deal with different kinds of content, such as markdown and HTML, and want to pick and choose plugins.

### What are the requirements for installing unified?

The package is ESM only and installs with npm on Node.js version 16 or newer. Deno and browser builds are available through esm.sh, with the readme showing unified@11 as the import path.

### Why is a processor from a module frozen in unified?

Processors exposed from a module should not be configured directly, because that would change their behaviour for all users of that module. They are frozen and should be called to create a new processor before use.

### Where do plugins report problems in a unified pipeline?

Messages are stored on the vfile, which the readme describes as the file format that stores data, metadata and messages about files for unified and plugins. A reporter such as vfile-reporter can print those messages separately from the compiled output.

## Sources

- [License: MIT](https://github.com/unifiedjs/unified/blob/main/LICENSE)
- [Project website](https://unifiedjs.com)
- [README](https://github.com/unifiedjs/unified/blob/main/README.md)
- [Releases](https://github.com/unifiedjs/unified/releases)
- [unifiedjs/unified on GitHub](https://github.com/unifiedjs/unified)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/unifiedjs-unified
