react-markdown
Safely render Markdown as React elements, no dangerouslySetInnerHTML required
Repository Health
Technical Analysis
react-markdown is a React component that turns a Markdown string into a tree of React elements instead of raw HTML, so nothing ever passes through dangerouslySetInnerHTML and the app stays safe from injected scripts by default. Under the hood it delegates parsing and transformation to the unified ecosystem (remark for Markdown, rehype for HTML), which means it inherits a mature plugin system, full CommonMark compliance, and optional GitHub Flavored Markdown support via remark-gfm.
Beyond safety, its main draw is customizability: any HTML tag produced by the render can be swapped for a React component via the components prop, letting consumers replace <a>, <img>, or <code> with app-specific implementations (routed links, lazy images, syntax-highlighted code blocks) without forking the renderer. Three entry points cover different rendering needs — a synchronous Markdown component for the common case, MarkdownAsync for server-side async plugins, and MarkdownHooks for client-side async plugins via React hooks.
What You Get
- A drop-in
<Markdown>component that renders a Markdown string prop straight to React elements - Automatic protection against script injection — HTML in the source markdown is stripped or escaped by default via a safe unified pipeline
- A
componentsprop to remap any rendered tag (headings, links, images, code blocks, tables) to your own React components remarkPluginsandrehypePluginsarrays for hooking into the wider unified plugin ecosystem (GFM tables/strikethrough, footnotes, math, syntax highlighting, table of contents, and more)MarkdownAsyncandMarkdownHooksvariants for rendering with async plugins on the server or client respectively- A configurable
urlTransformhook (with a safe default) to sanitize or rewrite every URL-bearing attribute in the output
Common Use Cases
- Rendering user-authored Markdown (comments, README previews, CMS content) safely in a React app without hand-rolling XSS sanitization
- Building a docs or blog site where Markdown needs to render through the app’s own design-system components instead of raw HTML tags
- Adding GitHub Flavored Markdown features (tables, task lists, strikethrough, autolinks) via remark-gfm on top of the base renderer
- Rendering LLM chat responses that come back as Markdown, with custom components for code blocks, links, and citations
Under The Hood
Architecture — The package exports Markdown (sync), MarkdownAsync (async, server-safe), and MarkdownHooks (async via React hooks) from lib/index.js. Internally it builds a unified() processor chaining remarkParse → user remarkPlugins → remarkRehype (with allowDangerousHtml: true so raw HTML survives as a raw node instead of being silently dropped) → user rehypePlugins. createFile() wraps the Markdown string in a VFile. After processing, a post() step runs a single unist-util-visit pass over the resulting hast tree to: reject deprecated pre-v6 props with actionable errors (via devlop’s unreachable()), convert or strip raw HTML nodes depending on skipHtml, rewrite every URL-bearing attribute through urlTransform/defaultUrlTransform (a protocol-allowlist regex), and filter elements via allowedElements/disallowedElements/allowElement. Finally hast-util-to-jsx-runtime’s toJsxRuntime() turns the filtered hast tree into React elements using the automatic JSX runtime, passing the original hast node to matched custom components via passNode. MarkdownHooks wraps this same pipeline in useMemo/useEffect/useState with a cancellation guard, deferring async-plugin work to the client without blocking initial render.
Tech Stack — A single index.js re-export plus a ~450-line lib/index.js, authored as pure ESM ("type": "module") checked-JS-with-JSDoc rather than .ts source, with tsc emitting the shipped .d.ts. Runtime dependencies are entirely from the unified/remark/rehype ecosystem (unified, remark-parse, remark-rehype, hast-util-to-jsx-runtime, html-url-attributes, unist-util-visit, vfile, devlop), plus type-only @types/hast/@types/mdast. React is a peer dependency only (>=18), never bundled. Dev tooling is Node’s built-in test runner (not Jest/Vitest), xo/prettier for lint and format, c8 for coverage, and type-coverage for strict type enforcement.
Code Quality — test.jsx is a single 1,280-line, 87-case suite covering the three exported components, deprecated-prop error paths, element allow/deny-listing, custom components, plugin composition, URL transforms, and SSR streaming, run via node:test with global-jsdom and @testing-library/react. The test script gates on c8 --100 (100% statement coverage) and type-coverage --at-least 100 --strict. Naming is terse and consistent (createProcessor/createFile/post), and error handling favors explicit, descriptive unreachable() throws that point at a changelog anchor for every removed/renamed legacy option rather than failing silently.
API Design — The public surface is deliberately small: a default Markdown export plus two async variants, so the common case is <Markdown>{md}</Markdown> with zero required configuration. Extensibility layers on cleanly via remarkPlugins/rehypePlugins arrays (the same plugin objects used across the broader unified ecosystem) and a components map that mirrors JSX.IntrinsicElements, so anyone familiar with remark/rehype faces almost no new API surface. Deprecated pre-v6 props throw actionable errors instead of silently misbehaving — unusually good DX for a library with a long breaking-change history. The readme is extensive, with runnable examples for plugins, custom components, and math/syntax-highlighting integrations.
Used by 165 apps in this directory
Argo Workflows
Data Engineering · Devops
The most popular Kubernetes-native workflow engine for orchestrating containerized DAGs, ML pipelines, CI/CD, and parallel batch jobs at scale.
Arkon
AI Assistants · Knowledge Management · Mcp
Self-hosted enterprise AI knowledge hub that compiles internal docs into a scoped, reviewable wiki and serves it to Claude and other LLMs through an MCP server.
Arroyo
Analytics · Data Engineering
A distributed stream processing engine written in Rust that lets you write SQL to run stateful, real-time computations over data streams with subsecond results.
AutoGen
AI Development · Automation
Build autonomous and human-in-the-loop multi-agent AI systems with a layered, event-driven Python and .NET framework pioneered at Microsoft Research.
AutoGPT
AI Assistants · Automation · Productivity
Build, deploy, and run autonomous AI agents that automate complex multi-step workflows using a visual block-based graph editor.
Banana Slides
AI Design Tools · Productivity
AI-native PPT generator with Vibe editing, multi-LLM support, and fully editable PPTX export
Blinko
Knowledge Management · Note Taking
A self-hosted, AI-powered card note-taking tool that lets you capture fleeting thoughts instantly and retrieve them with natural language search.
Bubble Lab
AI Development · Automation
Open-core workflow engine for building AI-powered automations in TypeScript that run natively inside Slack — no context switching required.
Bun
Developer Tools
An all-in-one JavaScript and TypeScript toolkit — one Rust-and-JavaScriptCore binary that replaces Node.js, npm, a bundler, and a test runner with faster equivalents.