Markdown
freeMarkdown renders streamed or static text as themed, incomplete-safe markdown with built-in code highlighting.
streamdown
Preview
Dark
Deployment summary
Three services updated cleanly and no errors were reported.
auth-service— 2m 14sbilling-service— 1m 48snotifications-service— 57s
See the full log [blocked] for details.
import { Markdown } from '@/components/composites/Markdown';
const content = `## Deployment summary
Three services updated cleanly and no errors were reported.
- \`auth-service\` — 2m 14s
- \`billing-service\` — 1m 48s
- \`notifications-service\` — 57s
See the [full log](#) for details.`;
export default function UsageDemo() {
return <Markdown>{content}</Markdown>;
}Installation
Add this component with the NateUI CLI.
npx nateui@latest add MarkdownExamples
Code Block
Fenced code renders through streamdown's own built-in highlighter — a light/dark-aware theme and a copy button, with no extra wiring required.
Preview
Dark
Here is a small helper:
import { Markdown } from '@/components/composites/Markdown';
const content = `Here is a small helper:
\`\`\`ts
function clamp(value: number, min: number, max: number): number {
return Math.min(Math.max(value, min), max)
}
\`\`\`
`;
export default function CodeBlockDemo() {
return <Markdown>{content}</Markdown>;
}Table
Tables get a minimal bordered treatment with a horizontal-scroll wrapper for narrow containers.
Preview
Dark
| Service | Status | Latency |
|---|---|---|
| auth-service | Healthy | 42ms |
| billing-service | Healthy | 58ms |
| notifications-service | Degraded | 210ms |
import { Markdown } from '@/components/composites/Markdown';
const content = `| Service | Status | Latency |
| --- | --- | --- |
| auth-service | Healthy | 42ms |
| billing-service | Healthy | 58ms |
| notifications-service | Degraded | 210ms |`;
export default function TableDemo() {
return <Markdown>{content}</Markdown>;
}Streaming
streamdown tolerates unclosed markdown syntax mid-stream — the same content, revealed a few characters at a time, never flashes broken formatting while it arrives.
Preview
Dark
import { useEffect, useState } from 'react';
import { Markdown } from '@/components/composites/Markdown';
const fullText = `**Streaming a reply:**
This paragraph is being revealed a few characters at a time, and the bold text above stayed intact the whole way through — even while its closing \`**\` had not arrived yet.`;
export default function StreamingDemo() {
const [length, setLength] = useState(0);
useEffect(() => {
if (length >= fullText.length) return;
const id = setTimeout(() => setLength((current) => current + 3), 30);
return () => clearTimeout(id);
}, [length]);
return <Markdown>{fullText.slice(0, length)}</Markdown>;
}API
Markdown
| Prop | Description | Type | Default |
|---|---|---|---|
children | The markdown source to render. | string | — |
className | Classes merged with the rendered root. | string | — |