StreamMDX
HomeDocsGuidesMdx And Html
Browse docs

MDX and HTML in StreamMDX

Why MDX is optional

StreamMDX treats MDX as an opt-in feature. Plain Markdown streams fast and predictably. MDX adds custom components, but requires compilation. You can enable it only where you need it:

tsx
<StreamingMarkdown
  text={content}
  features={{ mdx: true, html: true }}
  mdxCompileMode="worker"
/>

If you do not need MDX, leave it off for the simplest and fastest path.

Compile strategies

Worker mode (default recommendation)

  • all compilation happens in the worker
  • no server endpoint needed
  • worker and server behavior are identical
tsx
<StreamingMarkdown mdxCompileMode="worker" />

Server mode

  • you host a compile endpoint (useful for stricter build control)
  • the worker requests compiled output
  • you must keep server and worker compile settings aligned
tsx
<StreamingMarkdown mdxCompileMode="server" />

MDX component registry

MDX components are passed separately from block overrides:

tsx
const mdxComponents = {
  Callout: ({ title, children }: { title: string; children: React.ReactNode }) => (
    <div className="rounded border border-border p-4">
      <div className="font-semibold">{title}</div>
      <div className="mt-2">{children}</div>
    </div>
  ),
};

<StreamingMarkdown text={content} mdxComponents={mdxComponents} />

HTML blocks

When HTML is enabled, raw HTML blocks are sanitized and rendered with a configurable allowlist. You can also swap HTML tags for your own components:

tsx
const htmlElements = {
  blockquote: ({ children }: { children: React.ReactNode }) => (
    <blockquote className="border-l-2 border-border pl-4 text-muted-old">{children}</blockquote>
  ),
};

<StreamingMarkdown text={content} htmlElements={htmlElements} features={{ html: true }} />

When to use each feature

  • Markdown only: most content, best performance
  • HTML: when you need raw HTML tags (tables, custom spans)
  • MDX: when you need React components in content

Example MDX snippet

plain text
<Callout title="Heads up">
  This is a custom component rendered inside the stream.
</Callout>

Here is a YouTube embed:

<YouTube videoId="dQw4w9WgXcQ" />

In worker mode, this compiles inside the worker and renders as soon as the block completes.