Mathematics

Render beautiful LaTeX equations with KaTeX support in Streamdown.

Streamdown provides built-in support for rendering mathematical expressions using LaTeX syntax, powered by KaTeX. Write complex equations and formulas that render beautifully alongside your content.

Enabling Math

Math rendering requires the math plugin. Install it:

npm install @streamdown/math

Then import and pass the plugin to Streamdown:

app/page.tsx
import { Streamdown } from "streamdown";
import { math } from "@streamdown/math";
import "katex/dist/katex.min.css";

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

Syntax

Streamdown uses double dollar signs ($$) to delimit mathematical expressions. Unlike traditional LaTeX, single dollar signs ($) are not used to avoid conflicts with currency symbols in regular text.

Inline Math

Wrap inline mathematical expressions with $$:

The quadratic formula is $$x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$$ for solving equations.

Renders as: The quadratic formula is x=b±b24ac2ax = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} for solving equations.

Block Math

For display-style equations, place $$ delimiters on separate lines:

$$
E = mc^2
$$

This renders the equation centered and larger:

E=mc2E = mc^2

Common Mathematical Expressions

Fractions

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

Example: 12\frac{1}{2}, a+bcd\frac{a + b}{c - d}

Square Roots

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

Example: 16=4\sqrt{16} = 4, 273=3\sqrt[3]{27} = 3

Exponents and Subscripts

$$x^2$$ or $$x_i$$ or $$x_i^2$$

Example: a2+b2=c2a^2 + b^2 = c^2, x1,x2,,xnx_1, x_2, \ldots, x_n

Greek Letters

$$\alpha, \beta, \gamma, \delta, \theta, \pi, \sigma, \omega$$
$$\Gamma, \Delta, \Theta, \Pi, \Sigma, \Omega$$

Common letters: α,β,γ,δ,ϵ,π,σ,ϕ,ω\alpha, \beta, \gamma, \delta, \epsilon, \pi, \sigma, \phi, \omega

Summations

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

The sum of first nn natural numbers: i=1ni=n(n+1)2\sum_{i=1}^{n} i = \frac{n(n+1)}{2}

Integrals

$$\int_{a}^{b} f(x) \, dx$$

Definite integral: 01x2dx=13\int_{0}^{1} x^2 \, dx = \frac{1}{3}

Limits

$$\lim_{x \to \infty} \frac{1}{x} = 0$$

Example: limx0sinxx=1\lim_{x \to 0} \frac{\sin x}{x} = 1

Matrices

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

A 2×2 matrix:

[1234]\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix}

Advanced Examples

The Quadratic Formula

$$
x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
$$
x=b±b24ac2ax = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}

Euler's Identity

$$
e^{i\pi} + 1 = 0
$$
eiπ+1=0e^{i\pi} + 1 = 0

Normal Distribution

$$
f(x) = \frac{1}{\sigma\sqrt{2\pi}} e^{-\frac{1}{2}\left(\frac{x-\mu}{\sigma}\right)^2}
$$

The probability density function:

f(x)=1σ2πe12(xμσ)2f(x) = \frac{1}{\sigma\sqrt{2\pi}} e^{-\frac{1}{2}\left(\frac{x-\mu}{\sigma}\right)^2}

Taylor Series

$$
e^x = \sum_{n=0}^{\infty} \frac{x^n}{n!} = 1 + x + \frac{x^2}{2!} + \frac{x^3}{3!} + \cdots
$$
ex=n=0xnn!=1+x+x22!+x33!+e^x = \sum_{n=0}^{\infty} \frac{x^n}{n!} = 1 + x + \frac{x^2}{2!} + \frac{x^3}{3!} + \cdots

Integration by Parts

$$
\int u \, dv = uv - \int v \, du
$$
udv=uvvdu\int u \, dv = uv - \int v \, du

Special Operators and Symbols

Comparison Operators

$$\leq$$ $$\geq$$ $$\neq$$ $$\approx$$ $$\equiv$$

xyx \leq y, aba \geq b, x0x \neq 0, π3.14\pi \approx 3.14, ab(modn)a \equiv b \pmod{n}

Set Notation

$$\in$$ $$\notin$$ $$\subset$$ $$\subseteq$$ $$\cup$$ $$\cap$$ $$\emptyset$$

xAx \in A, yBy \notin B, ABA \subset B, ABA \cup B, ABA \cap B, \emptyset

Logic Symbols

$$\land$$ $$\lor$$ $$\neg$$ $$\implies$$ $$\iff$$ $$\forall$$ $$\exists$$

pqp \land q, pqp \lor q, ¬p\neg p, p    qp \implies q, p    qp \iff q, x\forall x, y\exists y

Calculus Notation

$$\frac{dy}{dx}$$ $$\frac{\partial f}{\partial x}$$ $$\nabla$$ $$\infty$$

Derivative: dydx\frac{dy}{dx}, Partial: fx\frac{\partial f}{\partial x}, Gradient: f\nabla f, Infinity: \infty

Configuration

Custom Error Color

Customize how errors are displayed using createMathPlugin:

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

const math = createMathPlugin({
  errorColor: '#dc2626',
});

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

Complete Configuration Example

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

const math = createMathPlugin({
  singleDollarTextMath: true, // Enable $...$ syntax (default: false)
  errorColor: '#dc2626',      // Custom error color (default: "var(--color-muted-foreground)")
});

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

Disable Math Support

If you don't need math support, you can exclude the plugins:

import { Streamdown } from 'streamdown';

export default function Page() {
  return (
    <Streamdown
      remarkPlugins={[]} // Removes remark-math
      rehypePlugins={[]} // Removes rehype-katex
    >
      {markdown}
    </Streamdown>
  );
}

Note: This will remove all default plugins, so you'll need to add back any others you need.

Streaming Considerations

Incomplete Equations

Streamdown's unterminated block parser handles incomplete equations gracefully:

$$
E = mc^

During streaming, the parser detects the incomplete block-level equation and adds the closing $$ delimiter, ensuring proper rendering even before the equation is complete.

Inline vs Block Detection

The parser distinguishes between inline and block math:

  • Inline: E=mc2E = mc^2 (same line)
  • Block: Separate lines with newlines
This is inline $$E = mc^2$$ math.

$$
E = mc^2
$$

This is block math.

Accessibility

Mathematical expressions rendered by KaTeX include:

  • MathML - Machine-readable math representation
  • Title Attributes - LaTeX source in tooltips
  • Semantic HTML - Proper structure for screen readers
  • Scalable Typography - Math scales with text size settings

Performance

KaTeX is chosen for its performance characteristics:

  • Fast Rendering - 2-3x faster than MathJax
  • No JavaScript Runtime - Pure CSS styling (after initial render)
  • Small Bundle - Minimal impact on page load
  • Cached Parsing - Streamdown memoizes rendered equations

Common Issues

Escaping Backslashes

In JavaScript/TypeScript strings, backslashes need to be escaped:

// ❌ Wrong
const markdown = "$\frac{1}{2}$";

// ✅ Correct
const markdown = "$$\\frac{1}{2}$$";

// ✅ Or use template literals
const markdown = `$$\frac{1}{2}$$`;

Currency vs Math

Streamdown uses $$ for math to avoid conflicts with currency:

This item costs $5 and that one costs $10. (These are currency symbols)

This equation $$x = 5$$ is mathematical notation. (This is math)

Spacing in Equations

Use \, for thin space, \: for medium space, \; for thick space:

$$\int f(x) \, dx$$

Better spacing: f(x)dx\int f(x) \, dx

Resources

Plugin Interface

The Math plugin implements the MathPlugin interface:

interface MathPlugin {
  name: "katex";
  type: "math";
  remarkPlugin: Pluggable;  // remark-math for parsing
  rehypePlugin: Pluggable;  // rehype-katex for rendering
  getStyles?: () => string; // Returns "katex/dist/katex.min.css"
}

Use getStyles() to get the CSS path programmatically:

import { math } from '@streamdown/math';

const cssPath = math.getStyles?.();
// "katex/dist/katex.min.css"

Best Practices

Keep Equations Readable

Break complex equations into steps:

Start with the equation:

$$
f(x) = ax^2 + bx + c
$$

Complete the square:

$$
f(x) = a\left(x + \frac{b}{2a}\right)^2 + c - \frac{b^2}{4a}
$$

Add Context

Explain your equations:

The Pythagorean theorem states that for a right triangle:

$$
a^2 + b^2 = c^2
$$

where $$a$$ and $$b$$ are the legs and $$c$$ is the hypotenuse.

Use Block Math for Complex Expressions

Reserve inline math for simple expressions:

✅ Good: The slope is $$m = \frac{y_2 - y_1}{x_2 - x_1}$$

❌ Avoid: $$\int_{-\infty}^{\infty} e^{-x^2} \, dx = \sqrt{\pi}$$ in the middle of text

✅ Better:

$$
\int_{-\infty}^{\infty} e^{-x^2} \, dx = \sqrt{\pi}
$$