Markdown Rendering

The documentation template uses Streamdown as its markdown renderer. Streamdown is purpose-built for streaming content from AI models, handling incomplete syntax gracefully while delivering beautiful output with full plugin support.

Overview

Unlike traditional markdown renderers, Streamdown intelligently handles incomplete markdown by detecting unterminated syntax and applying progressive formatting. This makes it ideal for both static documentation and AI-powered streaming content.

Drop-in replacement

Streamdown works as a drop-in replacement for react-markdown. If you're already using react-markdown, migrating is straightforward.

Live demo

Watch Streamdown render markdown content in real-time, complete with code highlighting, maths rendering, and GFM table support:

Complete

Basic usage

At its simplest, Streamdown accepts a markdown string as children:

app/page.tsx
import { Streamdown } from "streamdown"

export default function Page() {
  const content = "# Hello World\n\nThis is **markdown** content."

  return (
    <Streamdown>
      {content}
    </Streamdown>
  )
}

With plugins

Enable syntax highlighting, maths, and diagrams by passing plugins:

components/docs/markdown-renderer.tsx
"use client"

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"

interface MarkdownRendererProps {
  content: string
  animated?: boolean
}

export function MarkdownRenderer({
  content,
  animated = false,
}: MarkdownRendererProps) {
  return (
    <Streamdown
      plugins={{ code, math, mermaid, cjk }}
      animated={animated}
    >
      {content}
    </Streamdown>
  )
}

Streaming mode

For AI-powered content that streams token by token, enable the animated prop:

components/ai-chat.tsx
"use client"

import { Streamdown } from "streamdown"
import { code } from "@streamdown/code"

export function AiResponse({ content, isStreaming }: {
  content: string
  isStreaming: boolean
}) {
  return (
    <Streamdown
      plugins={{ code }}
      animated={isStreaming}
    >
      {content}
    </Streamdown>
  )
}

Client component required

Streamdown must be used within a client component (marked with "use client") since it relies on browser APIs for rendering.

Customising plugins

Each plugin supports custom configuration via factory functions:

Custom code plugin
import { createCodePlugin } from "@streamdown/code"
import { createMathPlugin } from "@streamdown/math"

const code = createCodePlugin({
  themes: ["github-light", "github-dark"],
})

const math = createMathPlugin({
  singleDollarTextMath: true,
  errorColor: "#dc2626",
})

Refer to the Streamdown Plugins page for full configuration options for each plugin.