Alternative markdown renderer with built-in syntax highlighting, math, and diagram support.
Streamdown Rendering
This is a paragraph with bold text, italic text, and .
- First item
- Second item
- Third item
This is a blockquote with some quoted text.
| Name | Value |
|---|---|
| Alpha | 100 |
| Beta | 200 |
@assistant-ui/react-streamdown is an alternative to @assistant-ui/react-markdown. Choose based on your needs:
- react-markdown: Lightweight, bring-your-own syntax highlighter
- react-streamdown: Feature-rich with built-in Shiki, KaTeX, Mermaid support
Installation
npm install @assistant-ui/react-streamdown streamdownFor additional features, install the optional plugins:
npm install @streamdown/code @streamdown/math @streamdown/mermaid @streamdown/cjkBasic Usage
import { StreamdownTextPrimitive } from "@assistant-ui/react-streamdown";
// Inside a MessagePrimitive.Parts component
<MessagePrimitive.Parts components={{ Text: StreamdownText }} />
// Where StreamdownText is:
const StreamdownText = () => <StreamdownTextPrimitive />;With Plugins (Recommended)
import { StreamdownTextPrimitive } from "@assistant-ui/react-streamdown";
import { code } from "@streamdown/code";
import { math } from "@streamdown/math";
import { mermaid } from "@streamdown/mermaid";
import "katex/dist/katex.min.css";
const StreamdownText = () => (
<StreamdownTextPrimitive
plugins={{ code, math, mermaid }}
shikiTheme={["github-light", "github-dark"]}
/>
);When @streamdown/code is provided, the default theme is ["github-light", "github-dark"] for light/dark mode support.
Migration from react-markdown
If you're migrating from @assistant-ui/react-markdown, your existing SyntaxHighlighter and CodeHeader components still work:
import { StreamdownTextPrimitive } from "@assistant-ui/react-streamdown";
const StreamdownText = () => (
<StreamdownTextPrimitive
components={{
SyntaxHighlighter: MySyntaxHighlighter,
CodeHeader: MyCodeHeader,
}}
componentsByLanguage={{
mermaid: { SyntaxHighlighter: MermaidRenderer }
}}
/>
);Props
| Prop | Type | Default | Description |
|---|---|---|---|
mode | "streaming" | "static" | "streaming" | Rendering mode |
plugins | PluginConfig | - | Streamdown plugins (code, math, mermaid, cjk) |
shikiTheme | [string, string] | ["github-light", "github-dark"] | Light and dark theme for Shiki |
components | object | - | Custom components including SyntaxHighlighter and CodeHeader |
componentsByLanguage | object | - | Language-specific component overrides |
preprocess | (text: string) => string | - | Text preprocessing function |
controls | boolean | object | true | Enable/disable UI controls for code blocks and tables |
caret | "block" | "circle" | - | Streaming caret style |
mermaid | MermaidOptions | - | Mermaid diagram configuration |
linkSafety | LinkSafetyConfig | - | Link safety confirmation dialog |
remend | RemendConfig | - | Incomplete markdown auto-completion |
allowedTags | Record<string, string[]> | - | HTML tags whitelist |
containerProps | object | - | Props for the container div |
containerClassName | string | - | Class name for the container |
remarkRehypeOptions | object | - | Options passed to remark-rehype |
BlockComponent | ComponentType | - | Custom component for rendering blocks |
parseMarkdownIntoBlocksFn | (md: string) => string[] | - | Custom block parsing function |
parseIncompleteMarkdown | boolean | false | Parse incomplete markdown as-is (skip remend) |
security | SecurityConfig | - | URL/image security restrictions |
Plugin Configuration
Code Highlighting
import { code } from "@streamdown/code";
<StreamdownTextPrimitive
plugins={{ code }}
shikiTheme={["github-light", "github-dark"]}
/>Math (LaTeX)
import { math } from "@streamdown/math";
import "katex/dist/katex.min.css";
<StreamdownTextPrimitive plugins={{ math }} />Mermaid Diagrams
import { mermaid } from "@streamdown/mermaid";
<StreamdownTextPrimitive plugins={{ mermaid }} />CJK Text Optimization
import { cjk } from "@streamdown/cjk";
<StreamdownTextPrimitive plugins={{ cjk }} />Advanced Configuration
Mermaid Options
Customize Mermaid diagram rendering with configuration and error handling:
import { mermaid } from "@streamdown/mermaid";
<StreamdownTextPrimitive
plugins={{ mermaid }}
mermaid={{
config: { theme: "dark" },
errorComponent: ({ error, chart, retry }) => (
<div>
<p>Failed to render diagram: {error}</p>
<button onClick={retry}>Retry</button>
</div>
),
}}
/>Streaming Caret
Display a caret indicator during streaming:
<StreamdownTextPrimitive caret="block" /> // ▋
<StreamdownTextPrimitive caret="circle" /> // ●Link Safety
Show confirmation before opening external links:
<StreamdownTextPrimitive
linkSafety={{
enabled: true,
onLinkCheck: (url) => url.startsWith("https://trusted.com"),
}}
/>Incomplete Markdown Handling (Remend)
Configure how incomplete markdown syntax is handled during streaming:
<StreamdownTextPrimitive
remend={{
links: true, // Complete incomplete links
images: true, // Handle incomplete images
bold: true, // Complete **text → **text**
italic: true, // Complete *text → *text*
inlineCode: true, // Complete `code → `code`
katex: true, // Complete $$equation → $$equation$$
}}
/>Allowed HTML Tags
Allow specific HTML tags in markdown content:
<StreamdownTextPrimitive
allowedTags={{
div: ["class", "id"],
span: ["class", "style"],
iframe: ["src", "width", "height"],
}}
/>Security Configuration
Restrict allowed URLs for links and images. This overrides streamdown's default allow-all policy:
<StreamdownTextPrimitive
security={{
// Only allow links to trusted domains
allowedLinkPrefixes: ["https://example.com", "https://docs.example.com"],
// Only allow images from your CDN
allowedImagePrefixes: ["https://cdn.example.com"],
// Restrict protocols
allowedProtocols: ["https", "mailto"],
// Disable base64 data images
allowDataImages: false,
// CSS class for blocked elements
blockedLinkClass: "blocked-link",
blockedImageClass: "blocked-image",
}}
/>Detecting Inline vs Block Code
When building custom code components, you can use useIsStreamdownCodeBlock to detect whether you're inside a code block or inline code:
import { useIsStreamdownCodeBlock } from "@assistant-ui/react-streamdown";
function MyCodeComponent({ children, ...props }) {
const isCodeBlock = useIsStreamdownCodeBlock();
if (!isCodeBlock) {
return <code className="inline-code" {...props}>{children}</code>;
}
return <pre><code {...props}>{children}</code></pre>;
}You can also use useStreamdownPreProps to access the props passed to the parent <pre> element:
import { useStreamdownPreProps } from "@assistant-ui/react-streamdown";
function MyCodeComponent({ children }) {
const preProps = useStreamdownPreProps();
if (!preProps) {
// Inline code
return <code>{children}</code>;
}
// Block code - preProps contains className, node, etc.
return <code className={preProps.className}>{children}</code>;
}Comparison with react-markdown
| Feature | react-markdown | react-streamdown |
|---|---|---|
| Bundle size | Smaller | Larger (with plugins) |
| Syntax highlighting | Bring your own | Built-in Shiki |
| Math rendering | Manual setup | Built-in KaTeX |
| Mermaid diagrams | Manual setup | Built-in support |
| CJK optimization | None | Built-in |
| Streaming | smooth prop | mode + block-based |
Re-exported Utilities
The package re-exports useful utilities:
import {
// Context for accessing streamdown state
StreamdownContext,
// Parse markdown into blocks (for custom implementations)
parseMarkdownIntoBlocks,
// Hooks for custom code components
useIsStreamdownCodeBlock,
useStreamdownPreProps,
// Memo comparison utility for custom components
memoCompareNodes,
// Default Shiki theme: ["github-light", "github-dark"]
DEFAULT_SHIKI_THEME,
} from "@assistant-ui/react-streamdown";Available Types
import type {
// Component props
StreamdownTextPrimitiveProps,
SyntaxHighlighterProps,
CodeHeaderProps,
ComponentsByLanguage,
StreamdownTextComponents,
StreamdownProps,
// Plugin types
PluginConfig,
ResolvedPluginConfig,
CodeHighlighterPlugin,
DiagramPlugin,
MathPlugin,
CjkPlugin,
HighlightOptions,
// Shiki types
BundledTheme,
BundledLanguage,
// Configuration types
CaretStyle,
ControlsConfig,
MermaidOptions,
MermaidErrorComponentProps,
LinkSafetyConfig,
LinkSafetyModalProps,
RemendConfig,
RemendHandler,
AllowedTags,
RemarkRehypeOptions,
BlockProps,
SecurityConfig,
} from "@assistant-ui/react-streamdown";Related Components
- Markdown - Lightweight markdown with react-markdown
- Syntax Highlighting - Add code highlighting to react-markdown
- Mermaid - Render diagrams in react-markdown