Markdown
An answer's markdown, with tables and code blocks.
Monthly active users
Active users grew 12% in March, led by the new /teams page.
| Month | Users | Change |
|---|---|---|
| January | 18,240 | — |
| February | 19,880 | +9.0% |
| March | 22,270 | +12.0% |
To pull the same numbers yourself:
const users = await acme.metrics.activeUsers({
from: "2026-01-01",
to: "2026-03-31",
interval: "month",
});Figures leave out test accounts on
acme.com.
<Message from="assistant"> <MessageContent> <Markdown highlighter={highlightCode}>{answer}</Markdown> </MessageContent></Message>Installation
$ npx shadcn@latest add @constella/markdownUsage
import { Markdown } from "@/components/ai/markdown";<Markdown>{answer}</Markdown>Tables render on Table. Code blocks get a Copy Button. Links open in a new tab.
Streaming
Set streaming while the answer arrives. Unclosed code blocks, lists and emphasis render as if they were closed.
<Markdown streaming={status === "streaming"}>{text}</Markdown>Highlighter
Pass a highlighter from TanStack Highlight to color code blocks. Add its theme CSS once on the page.
import { createHighlighter } from "@tanstack/highlight/core";import { json, shell, ts } from "@tanstack/highlight/languages";import { createTanStackMarkdownHighlighter } from "@tanstack/highlight/markdown";
const highlighter = createTanStackMarkdownHighlighter( createHighlighter({ languages: [json, shell, ts] }));
<Markdown highlighter={highlighter}>{answer}</Markdown>;Components
Use components to replace a tag, or render a custom tag from an extension, such as a citation.
<Markdown components={{ "md-citation": AnswerCitation }} extensions={[citations]}> {answer}</Markdown>API Reference
| Prop | Adds |
|---|---|
streaming | Renders unclosed syntax as closed while text arrives. |
sx | Styles on the wrapping div, applied last. |
Headings start at h3, under the page's own. For the rest, see TanStack Markdown.