Streamdown ships with a plugin system that wires additional remark and rehype processors—plus custom React renderers—into the markdown pipeline. Plugins are passed as a single plugins prop and are fully tree-shakeable: you only pay for what you import.
Available plugins
| Package | Purpose | Key dependency |
|---|
@streamdown/code | Syntax highlighting for code blocks | Shiki |
@streamdown/math | LaTeX math rendering | KaTeX |
@streamdown/mermaid | Diagram rendering | Mermaid |
@streamdown/cjk | Chinese, Japanese, Korean text support | remark-cjk-friendly |
PluginConfig interface
All plugins are passed together via the plugins prop, which accepts a PluginConfig object:
interface PluginConfig {
cjk?: CjkPlugin;
code?: CodeHighlighterPlugin;
math?: MathPlugin;
mermaid?: DiagramPlugin;
renderers?: CustomRenderer[];
}
Every key is optional. You can use any combination of plugins together.
Passing plugins to Streamdown
import { Streamdown } from 'streamdown';
import { code } from '@streamdown/code';
import { math } from '@streamdown/math';
import { mermaid } from '@streamdown/mermaid';
import { cjk } from '@streamdown/cjk';
import 'katex/dist/katex.min.css';
export default function Chat({ markdown }: { markdown: string }) {
return (
<Streamdown plugins={{ code, math, mermaid, cjk }}>
{markdown}
</Streamdown>
);
}
Plugin type interfaces
Each plugin implements one of four typed interfaces exported from streamdown:
CodeHighlighterPlugin
Powered by Shiki. Handles syntax highlighting for fenced code blocks.
interface CodeHighlighterPlugin {
name: 'shiki';
type: 'code-highlighter';
getSupportedLanguages: () => BundledLanguage[];
getThemes: () => [ThemeInput, ThemeInput];
highlight: (
options: HighlightOptions,
callback?: (result: HighlightResult) => void
) => HighlightResult | null;
supportsLanguage: (language: BundledLanguage) => boolean;
}
MathPlugin
Powered by KaTeX via remark-math and rehype-katex.
interface MathPlugin {
name: 'katex';
type: 'math';
remarkPlugin: Pluggable;
rehypePlugin: Pluggable;
getStyles?: () => string;
}
DiagramPlugin
Powered by Mermaid. Detects mermaid code fences and renders them as interactive SVGs.
interface DiagramPlugin {
name: 'mermaid';
type: 'diagram';
language: string;
getMermaid: (config?: MermaidConfig) => MermaidInstance;
}
CjkPlugin
Injects remark plugins before and after remark-gfm to handle CJK text correctly.
interface CjkPlugin {
name: 'cjk';
type: 'cjk';
remarkPluginsBefore: Pluggable[];
remarkPluginsAfter: Pluggable[];
/** @deprecated Use remarkPluginsBefore and remarkPluginsAfter instead */
remarkPlugins: Pluggable[];
}
Plugin ordering
Streamdown manages plugin ordering automatically. When plugins are present, the remark pipeline is assembled as:
cjk.remarkPluginsBefore (e.g. remark-cjk-friendly)
- Default plugins:
remark-gfm, remark-code-meta
cjk.remarkPluginsAfter (e.g. autolink boundary splitting, strikethrough)
math.remarkPlugin (remark-math)
The rehype pipeline appends math.rehypePlugin (rehype-katex) after the default rehype plugins.
Full example: all plugins together
import { Streamdown } from 'streamdown';
import { createCodePlugin } from '@streamdown/code';
import { createMathPlugin } from '@streamdown/math';
import { createMermaidPlugin } from '@streamdown/mermaid';
import { createCjkPlugin } from '@streamdown/cjk';
import 'katex/dist/katex.min.css';
const code = createCodePlugin({
themes: ['github-light', 'github-dark'],
});
const math = createMathPlugin({
singleDollarTextMath: false,
errorColor: 'var(--color-muted-foreground)',
});
const mermaid = createMermaidPlugin({
config: { theme: 'default' },
});
const cjk = createCjkPlugin();
export default function Chat({ markdown }: { markdown: string }) {
return (
<Streamdown
plugins={{ code, math, mermaid, cjk }}
mermaid={{
config: { theme: 'default' },
}}
controls={{
code: { copy: true, download: true },
mermaid: { fullscreen: true, download: true, copy: true, panZoom: true },
}}
>
{markdown}
</Streamdown>
);
}
The mermaid prop on <Streamdown> controls runtime rendering options (theme, error component) and is separate from the plugins.mermaid entry, which provides the Mermaid library instance.