Skip to main content
The @streamdown/math plugin renders mathematical expressions using KaTeX. It wires remark-math (parsing) and rehype-katex (rendering) into the Streamdown pipeline and produces accessible MathML output alongside the visual representation.

Installation

1

Install the packages

npm install @streamdown/math
KaTeX is a dependency of @streamdown/math and will be installed automatically. You do not need to install it separately.
2

Import the KaTeX stylesheet

KaTeX requires its CSS to render correctly. Import it once at the root of your application:
layout.tsx
import 'katex/dist/katex.min.css';
Without this import, math expressions will render without proper spacing, sizing, and symbol fonts.
3

Pass the plugin to Streamdown

import { Streamdown } from 'streamdown';
import { math } from '@streamdown/math';
import 'katex/dist/katex.min.css';

export default function Chat({ markdown }: { markdown: string }) {
  return (
    <Streamdown plugins={{ math }}>
      {markdown}
    </Streamdown>
  );
}

Math syntax

Block math

Surround an expression with $$ on its own lines to render a centered, display-style equation:
$$
E = mc^2
$$
$$
x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
$$

Inline math

By default, $$...$$ on a single line renders inline:
The quadratic formula is $$x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$$ for any quadratic equation.

Single-dollar syntax

Single $...$ delimiters are disabled by default to avoid conflicts with currency symbols. Enable them explicitly:
import { createMathPlugin } from '@streamdown/math';

const math = createMathPlugin({
  singleDollarTextMath: true,
});
Enabling singleDollarTextMath will cause any $ in your content to be treated as a potential math delimiter, which may break currency formatting. Use with caution in user-generated content.

Configuration

createMathPlugin(options?)

interface MathPluginOptions {
  /**
   * KaTeX error color
   * @default "var(--color-muted-foreground)"
   */
  errorColor?: string;

  /**
   * Enable single dollar sign for inline math ($...$)
   * @default false
   */
  singleDollarTextMath?: boolean;
}
import { createMathPlugin } from '@streamdown/math';

const math = createMathPlugin({
  singleDollarTextMath: false,   // default
  errorColor: '#dc2626',         // red error highlight
});

API reference

MathPlugin

interface MathPlugin {
  name: 'katex';
  type: 'math';
  remarkPlugin: Pluggable;  // remark-math
  rehypePlugin: Pluggable;  // rehype-katex
  getStyles?: () => string;
}

getStyles()

Returns the path to the KaTeX CSS file for programmatic use:
import { math } from '@streamdown/math';

const cssPath = math.getStyles?.();
// Returns: "katex/dist/katex.min.css"
This is useful if you need to dynamically inject the stylesheet or reference the path in a build tool.

Pre-configured instance

@streamdown/math exports a pre-configured instance with default options:
import { math } from '@streamdown/math';
// Equivalent to: createMathPlugin()

Common examples

Fractions

$$\frac{numerator}{denominator}$$

Square roots

$$\sqrt{x}$$ or $$\sqrt[n]{x}$$

Summations

$$\sum_{i=1}^{n} i = \frac{n(n+1)}{2}$$

Matrices

$$
\begin{bmatrix}
a & b \\
c & d
\end{bmatrix}
$$

Greek letters

$$\alpha, \beta, \gamma, \delta, \pi, \sigma, \omega$$

Escaping backslashes

In JavaScript/TypeScript string literals, backslashes must be escaped:
// Incorrect — \f is not a valid escape sequence
const markdown = "$\frac{1}{2}$";

// Correct — double-escape the backslash
const markdown = "$$\\frac{1}{2}$$";

// Correct — template literals handle single backslashes
const markdown = `$$\frac{1}{2}$$`;

Build docs developers (and LLMs) love