# How pi-web Renders Markdown with Mermaid Diagrams and KaTeX Math

> Discover how pi-web renders Markdown with Mermaid diagrams and KaTeX math using a React-Markdown pipeline and custom components. Learn its unique rendering process.

- Repository: [Alex Yang/pi-web](https://github.com/agegr/pi-web)
- Tags: how-to-guide
- Published: 2026-07-26

---

**pi-web processes user-generated markdown through a React-Markdown pipeline that chains remark plugins for parsing, rehype plugins for transformation, and custom components for rendering interactive Mermaid diagrams and KaTeX-styled mathematics.**

The `agegr/pi-web` repository implements a sophisticated markdown processing system that extends standard React-Markdown capabilities to support technical documentation requirements. By combining specialized remark plugins, strict HTML sanitization, and lazy-loaded client-side rendering, the application safely transforms raw markdown strings into interactive documents featuring mathematical notation and flow diagrams.

## The Markdown Rendering Pipeline

The entry point in [`components/MarkdownBody.tsx`](https://github.com/agegr/pi-web/blob/main/components/MarkdownBody.tsx) orchestrates the entire transformation process. It receives raw markdown content, normalizes LaTeX display delimiters using `normalizeDisplayMath` from [`lib/markdown.ts`](https://github.com/agegr/pi-web/blob/main/lib/markdown.ts), and passes the processed string to the `<ReactMarkdown>` component with carefully configured plugin arrays.

## Parsing with Remark Plugins

Before transformation begins, the pipeline applies remark plugins to parse GitHub-flavored markdown extensions and mathematical expressions.

### GitHub-Flavored Markdown Support

The system incorporates `remark-gfm` to enable tables, task lists, strikethroughs, and other GitHub-specific syntax extensions. This allows content creators to use standard GitHub markdown features without additional configuration.

### Math Detection with Remark-Math

The `remark-math` plugin identifies inline math delimiters (`\(...\)`) and display math blocks (`$$...$$`), converting them into proper AST nodes for downstream processing. This detection occurs early in the pipeline, ensuring mathematical content is properly isolated before HTML generation.

## Transformation with Rehype Plugins

After parsing, the Abstract Syntax Tree passes through a series of rehype plugins defined in [`lib/markdown.ts`](https://github.com/agegr/pi-web/blob/main/lib/markdown.ts) and exported as `markdownRehypePlugins`. These plugins handle the final HTML generation and security sanitization.

### HTML Sanitization

The `rehype-sanitize` plugin applies a custom schema that strictly whitelists `code` elements by language class while stripping unsafe HTML attributes and potentially malicious tags. The `rehype-raw` plugin enables controlled HTML passthrough within markdown documents, allowing embedded HTML only after sanitization checks.

### KaTeX Math Rendering

The `rehype-katex` plugin transforms math nodes into static HTML using KaTeX. The required stylesheet is globally imported in [`app/layout.tsx`](https://github.com/agegr/pi-web/blob/main/app/layout.tsx) via [`katex.min.css`](https://github.com/agegr/pi-web/blob/main/katex.min.css), ensuring consistent typography across the application. This server-side compatible rendering produces static HTML that requires no client-side JavaScript to display.

## Handling Mermaid Diagrams

Unlike standard code blocks, Mermaid diagrams require special client-side handling and lazy loading to avoid bundling the heavy Mermaid library in the initial JavaScript payload.

### Code Block Detection

Inside [`components/MarkdownBody.tsx`](https://github.com/agegr/pi-web/blob/main/components/MarkdownBody.tsx), the component inspects fenced code block language identifiers. When the language equals `mermaid`, it renders the custom `<MermaidBlock>` component; otherwise, it uses the generic `<CodeBlock>` component. This branching logic ensures diagrams receive specialized handling while standard code blocks use the standard renderer.

### Lazy Client-Side Rendering

[`components/MermaidBlock.tsx`](https://github.com/agegr/pi-web/blob/main/components/MermaidBlock.tsx) dynamically imports the Mermaid library only when a user requests a diagram preview, eliminating server-side bundle size penalties. The component initializes Mermaid with a theme matching the current UI (`dark` or `default`), parses the diagram source, and stores the resulting SVG in component state. Users interact with a preview button that opens a zoom-able dialog for full diagram inspection.

## Theme Awareness

Both KaTeX mathematical styling and Mermaid diagram theming respond to the application's dark mode state through the `useTheme` hook. When users toggle between light and dark themes, mathematical equations update their color schemes automatically, and Mermaid re-renders diagrams with the appropriate color palette without requiring manual refresh or page reload.

## Complete Implementation Example

Here is a practical implementation showing how to render markdown content with both mathematical expressions and diagrams:

```tsx
import MarkdownBody from './components/MarkdownBody';

<MarkdownBody
  children={`

# Physics Documentation

The energy-mass equivalence is expressed as:

$$
E = mc^2
$$

Inline math example: \\( \\frac{d}{dx}f(x) \\)

System architecture:

\`\`\`mermaid
graph LR
    A[Client] --> B[Server]
    B --> C[Database]
\`\`\`
`}
  cwd="/home/user/project"
  onOpenFile={(path) => console.log('open', path)}
/>

```

The `mermaid` block renders as an interactive diagram preview, while the LaTeX equations display with proper KaTeX typography.

## Summary

- The `MarkdownBody` component in [`components/MarkdownBody.tsx`](https://github.com/agegr/pi-web/blob/main/components/MarkdownBody.tsx) serves as the primary entry point, normalizing LaTeX and coordinating React-Markdown with custom plugins.
- **Remark plugins** (`remark-gfm`, `remark-math`) parse GitHub-flavored extensions and mathematical notation into AST nodes.
- **Rehype plugins** (`rehype-sanitize`, `rehype-katex`, `rehype-raw`) sanitize HTML and convert math nodes into KaTeX-rendered HTML, with styles defined in [`app/layout.tsx`](https://github.com/agegr/pi-web/blob/main/app/layout.tsx).
- **Mermaid diagrams** are handled specially in [`components/MermaidBlock.tsx`](https://github.com/agegr/pi-web/blob/main/components/MermaidBlock.tsx) through lazy-loaded client-side rendering with theme-aware SVG generation.
- All mathematical and diagrammatic content automatically adapts to the application's dark mode setting via the `useTheme` hook.

## Frequently Asked Questions

### How does pi-web prevent XSS attacks when rendering raw markdown?

The pipeline implements a custom sanitization schema in [`lib/markdown.ts`](https://github.com/agegr/pi-web/blob/main/lib/markdown.ts) using `rehype-sanitize`, which strictly whitelists only safe HTML elements and specific `code` class attributes for syntax highlighting. Potentially dangerous tags and attributes are stripped before the content reaches the DOM, while `rehype-raw` allows controlled HTML passthrough under these constraints.

### Why is Mermaid rendered client-side instead of server-side?

[`components/MermaidBlock.tsx`](https://github.com/agegr/pi-web/blob/main/components/MermaidBlock.tsx) dynamically imports the Mermaid library only when a user requests a diagram preview, eliminating server-side bundle size penalties. This approach keeps the initial page load lightweight while still supporting complex diagram interactions like zooming and theming.

### What markdown extensions are supported beyond standard CommonMark?

The system supports GitHub-flavored markdown through `remark-gfm`, enabling tables, task lists, strikethroughs, and autolinks. Additionally, `remark-math` provides full support for LaTeX mathematical expressions using both inline `\(...\)` and display `$$...$$` delimiters.

### How does the application handle theme switching for mathematical content?

The KaTeX stylesheet imported in [`app/layout.tsx`](https://github.com/agegr/pi-web/blob/main/app/layout.tsx) responds to the application's dark mode state managed by the `useTheme` hook. When the theme toggles between `dark` and `default`, both the mathematical notation and Mermaid diagrams automatically re-render with appropriate color schemes without requiring manual refresh.