Markdown

An answer's markdown, with tables and code blocks.

View as Markdown

Monthly active users

Active users grew 12% in March, led by the new /teams page.

MonthUsersChange
January18,240—
February19,880+9.0%
March22,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/markdown

Usage

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

PropAdds
streamingRenders unclosed syntax as closed while text arrives.
sxStyles on the wrapping div, applied last.

Headings start at h3, under the page's own. For the rest, see TanStack Markdown.