TanStack Markdown: a 5 KB parser for blogs and docs, and what it refuses to parse
Tiny, fast Markdown parsing and rendering for blogs and documentation
At a glance
- What is it?
- TanStack Markdown is a TypeScript Markdown parser and renderer with a serializable AST, HTML, React and Octane adapters, and safe defaults for raw HTML. It is deliberately not CommonMark-complete, and the README says so.
- Who is it for?
- Adopt TanStack Markdown if your content is controlled technical prose and you want a small parser plus HTML, React or Octane renderers that agree with each other. Do not adopt it if you need full CommonMark, GFM, MDX or general content processing, since the README states it is intentionally none of those.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 17, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem TanStack Markdown targets: controlled technical prose, not arbitrary Markdown
Most Markdown libraries are built for the union of every Markdown dialect. That is the right call for a general-purpose tool and the wrong call for a documentation site whose authors all work in the same repository. TanStack Markdown takes the second position. The README describes the scope directly: it "targets controlled technical content", supports "the Markdown used by blogs and docs", and spends what it calls its remaining complexity budget on deterministic output, renderer parity, malformed-input resilience and small entry points.
The audience follows from that. This is for teams rendering blog posts and documentation pages where the source is reviewed before it ships. It is also for people who care about the size of what they ship: the README lists 5.0 KB gzip for the parser, 6.8 KB gzip for the HTML renderer, and 6.7 KB gzip for each of the React and Octane adapters, with zero runtime dependencies. Those numbers include the parser and exclude framework runtimes and syntax highlighters, which is the honest way to state them.
The phrase "deterministic output" is doing real work here. If the same source produces the same tree and the same markup every time, you can diff rendered output in CI and treat a change as a signal rather than noise.
A serializable AST, three renderers, and safe defaults for raw HTML
The architecture is a parse step followed by a render step, with the AST as the boundary between them. The README lists "serializable AST" as a property, which matters for two reasons. A tree that survives serialization can be cached, stored or passed between processes. It also means the renderers are consumers of the same structure rather than three independent implementations of Markdown.
That is what "renderer parity" refers to. The package exposes separate entry points, and the package.json exports map confirms them: the root, ./html, ./parser, ./react, ./octane, plus ./extensions/callouts, ./extensions/comment-components, ./extensions/docs, ./extensions/framework and ./extensions/headings. You import only the layer you need. A static site that wants a string takes the HTML entry point; a React app takes the React one; a tool that wants to inspect or transform content takes the parser.
Safety defaults are the other design decision worth naming. The README states "safe defaults for raw HTML and executable URLs". Raw HTML in Markdown is the usual injection path, and javascript: style URLs are the usual second one. Both are handled by default rather than behind a flag, which is the correct default for a library whose output goes onto a public page.
The extension surface is deliberately narrow. The README mentions "optional docs extensions and external syntax highlighting" and an "optional AI streaming profile". Syntax highlighting is not built in; the README points to a tested TanStack Highlight adapter that "registers only the languages you choose and returns escaped token markup inside Markdown-owned code containers". Keeping the highlighter outside is why the core numbers stay small.
Installing TanStack Markdown and rendering your first document
The package is published as @tanstack/markdown and the README gives pnpm as the install command:
pnpm add @tanstack/markdownIf you use an AI agent, the README also suggests running the intent installer so the agent can discover the package's task-specific skills:
npx @tanstack/intent@latest installThe fastest first use is the HTML renderer, which returns a string. The README's example is two lines:
import { renderHtml } from '@tanstack/markdown/html'
const html = renderHtml('# Fast by default')After running that, html holds the rendered markup for a single heading. There is no configuration object in the example and no options argument, which tells you the default path is meant to be the whole path for simple cases.
In a React app the adapter takes children instead of a string argument. The README's component example wraps the source directly:
import { Markdown } from '@tanstack/markdown/react'
export function Article({ source }: { source: string }) {
return <Markdown>{source}</Markdown>
}The Octane adapter follows the same shape with a different file extension and import path. Before you build on any of this, the README documents a verification command that runs the project's own checks:
pnpm run verifyAnd to include your own downstream content in the corpus gate, it gives an environment variable pointing at directories of Markdown:
MARKDOWN_CORPUS_DIRS=../tanstack.com/src/blog:../tanstack.com/docs \
pnpm run test:corpusThat last command is the most useful thing in the README for an evaluator. It runs the parser against a corpus of real documents and reports what it could not handle, which is a far better signal than reading a feature list.
The conformance gap is the point, and it is documented rather than hidden
The README states plainly that the project "is intentionally not a complete CommonMark, GFM, MDX, or general content-processing implementation". That single sentence disqualifies it for a large class of use cases, and the project seems to want it that way.
Concretely, this means you should not point it at user-submitted content and expect it to survive contact with every dialect. If your authors paste tables from a GFM-flavoured editor, or expect MDX components to be compiled, or need the full CommonMark edge-case behaviour around nested emphasis and list interruption, this is the wrong tool. The corpus reports exist precisely because compatibility is a spectrum and the project wants you to see where it sits rather than guess.
There is a second limitation that is easy to miss: the version number. The current release is 0.0.15, and the package.json confirms it. A 0.0.x line means the API can change without a major version bump, and the presence of a .changeset directory in the repository confirms the project uses changesets for release management. If you depend on the AST shape directly, treat that shape as unstable.
Finally, there is no homepage listed for the repository, and the README points to documentation files inside the repo (docs/overview.md, docs/quick-start.md, docs/reference/index.md and others) rather than to a hosted site. You will be reading the source tree to learn the API.
How it differs from remark and markdown-it
The obvious alternatives are remark (built on micromark and mdast) and markdown-it. Both are mature and both aim at broader Markdown coverage than TanStack Markdown claims for itself. The difference is not quality; it is the shape of the trade.
remark's model is a plugin pipeline over an AST, with the unified ecosystem supplying parsing, transformation and serialization as separate composable pieces. You get enormous reach, and you pay for it in dependency surface and in the number of decisions you have to make before anything renders. markdown-it is closer to a classic parser with a plugin system and a large rule set, and it is fast, but it also ships a much wider feature set than this project intends to.
TanStack Markdown's bet is narrower: one AST, several renderers that share it, zero runtime dependencies, and entry points small enough to quote in kilobytes. The README's own framing is that it supports the Markdown used by blogs and docs and then spends the rest on determinism and malformed-input resilience.
So the choice is about what you are optimizing. If you need to render whatever Markdown arrives from anywhere, remark or markdown-it will cover more ground. If your content is reviewed in a repository and you want the smallest thing that renders it consistently across HTML and a component framework, the size and parity arguments here are the ones that count.
Maintenance, licensing and what an upgrade actually costs
The repository is not archived, and the last push was on 2026-09-13. The most recent releases are v0.0.14 on 2026-09-11 and v0.0.15 on 2026-09-13, so the release cadence at the time of writing is measured in days, not months. The presence of a .changeset directory and a CHANGELOG.md at the repository root means version bumps are recorded deliberately.
Licensing is unambiguous where it matters: package.json declares "license": "MIT". That is permissive and imposes no copyleft obligation on your own code. This is not legal advice, and if you redistribute the package you should read the licence text yourself rather than take a summary.
Upgrade cost is driven by the 0.0.x version line. Because there is no stable major version, a patch or minor bump can change the AST or an entry point without ceremony. The repository ships a fixtures/ directory and a tests/ directory, and the README documents pnpm run verify, so the project's own regression surface is testable. Your own upgrade check should be the corpus gate with your content directories pointed at MARKDOWN_CORPUS_DIRS, run before and after the bump, with the rendered output diffed. That converts an upgrade from a hope into a comparison.
One cost worth flagging: syntax highlighting is external. The README recommends the TanStack Highlight adapter and notes it "registers only the languages you choose". That is a separate dependency and a separate upgrade track, and its bundle cost sits outside the numbers quoted for the core package.
Editorial conclusion
Adopt TanStack Markdown if your content is controlled technical prose and you want a small parser plus HTML, React or Octane renderers that agree with each other. Do not adopt it if you need full CommonMark, GFM, MDX or general content processing, since the README states it is intentionally none of those. Before committing, run pnpm run verify in a clone and check reports/conformance.md to see exactly which constructs fall outside the supported syntax profile.
Frequently asked questions
What is TanStack Markdown?
It is a small TypeScript Markdown parser and renderer for blogs and documentation, published as @tanstack/markdown. The README describes it as tiny, fast and deterministic, with a 5.0 KB gzip parser and separate HTML, React and Octane renderers that share one serializable AST.
How do I install TanStack Markdown?
The README gives a single command, pnpm add @tanstack/markdown. If you use an AI agent, it also suggests running npx @tanstack/intent@latest install so the agent can discover the package's task-specific skills.
How do I use TanStack Markdown in a React component?
Import Markdown from @tanstack/markdown/react and pass the Markdown source as children, as in the README's Article example. The Octane adapter uses the same component shape with a different import path.
Is TanStack Markdown a complete CommonMark implementation?
No. The README states that it is intentionally not a complete CommonMark, GFM, MDX, or general content-processing implementation, and that it targets the Markdown used by blogs and docs. The repository publishes a CommonMark compatibility accounting report under reports/conformance.md.
Does TanStack Markdown handle syntax highlighting?
Not in the core package. The README points to a tested TanStack Highlight adapter, which registers only the languages you choose and returns escaped token markup inside Markdown-owned code containers. Bundle sizes quoted for the core exclude syntax highlighters.
How do I check TanStack Markdown against my own Markdown files?
The README documents pnpm run test:corpus with the MARKDOWN_CORPUS_DIRS environment variable set to colon-separated directories of content. That runs the parser against your documents so you can see what it cannot handle before adopting it.
Community notes