Skip to main content
Watch: Claude Code Just Killed After Effects

Design & UI

Streamdown Chat Rendering

Use when rendering streaming LLM markdown in a chat UI with Streamdown. Covers incomplete-token safety mid-stream, a custom component map for a strict design system, and code-block handling. Also use when a half-arrived token renders as broken markup, a code fence flickers while streaming, or rendered output ignores the design contract. If markdown is rendered before it is complete, use this skill.

streamdownmarkdownchatstreamingreact

1 file

Description

Use when rendering streaming LLM markdown in a chat UI with Streamdown. Covers incomplete-token safety mid-stream, a custom component map for a strict design system, and code-block handling. Also use when a half-arrived token renders as broken markup, a code fence flickers while streaming, or rendered output ignores the design contract. If markdown is rendered before it is complete, use this skill.

Install
SKILL.md

name: streamdown-chat-rendering description: Use when rendering streaming LLM output as markdown in a chat interface with Streamdown (the streaming-safe react-markdown alternative from the AI SDK ecosystem). Covers incomplete-token safety, a custom component map for a strict design system, and code-block handling.

Streamdown Chat Rendering

When to trigger

Displaying assistant messages that arrive token by token and contain markdown (headings, lists, code fences). Plain react-markdown re-parses the whole string every token and flickers or mis-renders half-open syntax mid-stream.

Why Streamdown over react-markdown here

Streamdown is built for text that is still arriving: it handles an unterminated code fence, a half-written table, or an incomplete link without collapsing the layout on every keystroke. Render the accumulated text directly:

import { Streamdown } from "streamdown";
import remarkGfm from "remark-gfm";

<Streamdown remarkPlugins={[remarkGfm]} components={MARKDOWN_COMPONENTS}>
  {text}
</Streamdown>

Match the design contract with a component map

Streamdown renders default HTML elements. In a system with square corners, hairline borders, and no gradients, pass a components map so every element matches instead of shipping library defaults:

const MARKDOWN_COMPONENTS = {
  a: (props) => <a className="underline underline-offset-2" {...props} />,
  code: (props) => <code className="bg-neutral-100 px-1 font-mono text-[0.9em]" {...props} />,
  pre: (props) => <pre className="border border-black/10 bg-neutral-50 p-3 overflow-x-auto" {...props} />,
};

Streaming UX details

  • Show a blinking caret only while isStreaming && !text so an empty assistant bubble does not sit blank before the first token.
  • Detect a message that is a single fenced code block and let it go full width; wrap normal prose to a readable max width.

Pitfalls

  • Re-mounting the Streamdown component on every token (a changing key) throws away its incremental work and reintroduces flicker. Keep a stable key and change only the children.
  • Leaving the default component styles ships rounded corners and library colors into a hard-edged system. Supply the component map.
  • Rendering untrusted markdown without sanitizing links can inject javascript: URLs. Constrain or sanitize the a handler.
AI Development Stack

Get Smarter About AI Dev

New tutorials, open-source projects, and deep dives on coding agents - delivered weekly.

One email per weekReal code, not theoryFree forever