Skip to main content
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

PackagePurposeKey dependency
@streamdown/codeSyntax highlighting for code blocksShiki
@streamdown/mathLaTeX math renderingKaTeX
@streamdown/mermaidDiagram renderingMermaid
@streamdown/cjkChinese, Japanese, Korean text supportremark-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:
  1. cjk.remarkPluginsBefore (e.g. remark-cjk-friendly)
  2. Default plugins: remark-gfm, remark-code-meta
  3. cjk.remarkPluginsAfter (e.g. autolink boundary splitting, strikethrough)
  4. 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.

Build docs developers (and LLMs) love