react-markdown. You can use it anywhere you render markdown — in an AI chat interface, a blog post, or a documentation page.
Basic usage with the AI SDK
Streamdown is designed to work with AI streaming out of the box. The key props are:isAnimating— set totruewhile the stream is active so Streamdown knows content is incompleteanimated— enables character-by-character animation as tokens arriveplugins— opt-in plugin bundles for code highlighting, math, diagrams, and CJK
app/chat.tsx
Each plugin is optional. Install only the ones you need and add matching
@source entries to your globals.css. See Getting started for Tailwind setup details.Streaming mode vs static mode
Streamdown operates in two modes, controlled by themode prop.
- Streaming (default)
- Static
Streaming mode (
mode="streaming") is the default. It is optimized for content that arrives incrementally:- Parses markdown into independent blocks so already-rendered content is not re-rendered when new tokens arrive
- Applies the
remendpreprocessor to gracefully handle unterminated markdown constructs (unclosed code fences, incomplete bold, etc.) - Uses
useTransitionto keep the UI responsive during rapid updates - Tracks
isAnimatingstate to disable copy buttons while content is live
Props overview
isAnimating
Set isAnimating={true} while the stream is active. This disables interactive controls (copy buttons, download buttons) until streaming completes, preventing user actions on partial content. It also gates the caret display and the animation plugin.
animated
Enables character-by-character animation as new tokens arrive. Pass true for default animation settings, or an AnimateOptions object to customize behavior.
The
animated prop requires streamdown/styles.css to be imported in your app.mode
Controls the rendering strategy. Defaults to "streaming".
dir
Sets the text direction for rendered blocks. Use "auto" to detect direction per-block using the first strong character algorithm — useful for mixed-language AI responses.
caret
Shows a visual caret indicator at the end of the streaming output. Only visible while isAnimating is true. Hidden automatically when the last block is an incomplete code fence or table.
plugins
Opt-in plugin bundles for extended functionality. Each plugin is a separate package.
| Plugin key | Package | Provides |
|---|---|---|
code | @streamdown/code | Shiki syntax highlighting for code blocks |
mermaid | @streamdown/mermaid | Mermaid diagram rendering |
math | @streamdown/math | LaTeX math via KaTeX |
cjk | @streamdown/cjk | CJK-friendly word breaking |
Custom component overrides
Pass acomponents map to replace how any HTML element is rendered. This follows the same API as react-markdown.
The
inlineCode key is a Streamdown-specific shorthand. When provided, it overrides inline code elements only, while block code elements continue using Streamdown’s built-in code block renderer.Custom rehype and remark plugins
Streamdown includes a default set of plugins:rehype-raw, rehype-sanitize, rehype-harden, and remark-gfm. You can extend or replace these by passing rehypePlugins or remarkPlugins.
Block-level rendering
In streaming mode, Streamdown splits markdown into independent blocks before rendering. Each block is a memoizedBlock component — only the last (incomplete) block re-renders as new tokens arrive. Previously completed blocks are not touched.
You can provide a custom BlockComponent to wrap each block, or a custom parseMarkdownIntoBlocksFn if you need different block splitting logic:
BlockProps type includes:
content— the raw markdown string for this blockindex— zero-based position in the block listisIncomplete—truewhen this is the last block andisAnimatingistruewith an unclosed code fencedir— resolved text direction for the block (whendir="auto"is set onStreamdown)
