Syntax Highlighting

Code block syntax highlighting with react-shiki or react-syntax-highlighter.

Syntax highlighting is not enabled in markdown by default.
typescript

assistant-ui provides two options for syntax highlighting:

  • react-shiki (recommended for performance & dynamic language support)
  • react-syntax-highlighter (legacy - Prism or Highlight.js based)

react-shiki

Add shiki-highlighter

npx shadcn@latest add https://r.assistant-ui.com/shiki-highlighter.json

This adds a /components/assistant-ui/shiki-highlighter.tsx file to your project and installs the react-shiki dependency. The highlighter can be customized by editing the config in the shiki-highlighter.tsx file.

Add it to defaultComponents in markdown-text.tsx

/components/assistant-ui/markdown-text.tsx
import { SyntaxHighlighter } from "./shiki-highlighter";

export const defaultComponents = memoizeMarkdownComponents({
  SyntaxHighlighter: SyntaxHighlighter,
  h1: /* ... */,
  // ...other elements...
});

Options

See react-shiki documentation for all available options.

Key options:

  • theme - Shiki theme or multi-theme object ({ light, dark, ... })
  • language - Language for highlighting (default: "text")
  • defaultColor - Default color mode (string | false, e.g. light-dark())
  • delay - Delay between highlights, useful for streaming (default: 0)
  • customLanguages - Custom languages to preload for dynamic support
  • codeToHastOptions - All other options accepted by Shiki's codeToHast

Dual/multi theme support

To use multiple themes, pass a theme object:

/components/assistant-ui/shiki-highlighter.tsx
<ShikiHighlighter
  /* ... */
  theme={{
    light: "github-light",
    dark: "github-dark",
  }}
  defaultColor="light-dark()"
  /* ... */
>

Note: The shiki-highlighter component sets defaultColor="light-dark()" automatically. Only set this manually if using ShikiHighlighter directly.

With defaultColor="light-dark()", theme switching is automatic based on your site's color-scheme. No custom Shiki CSS overrides are required.

Set color-scheme on your app root:

System-based (follows OS/browser preference):

globals.css
:root {
  color-scheme: light dark;
}

Class-based theme switching:

globals.css
:root {
  color-scheme: light;
}
:root.dark {
  color-scheme: dark;
}

If you need broader support for older browsers, you can still use the manual CSS-variable switching approach from the Shiki dual-theme docs.

For more information:

Bundle Optimization

By default, react-shiki includes the full Shiki bundle, which contains all supported languages and themes.

To reduce bundle size, you can use the web bundle by changing the import to react-shiki/web, to include a smaller bundle of web related languages:

/components/assistant-ui/shiki-highlighter.tsx
import ShikiHighlighter, { type ShikiHighlighterProps } from "react-shiki/web";

Custom Bundles

For strict bundle size control, react-shiki also supports custom bundles created using createHighlighterCore from react-shiki/core (re-exported from Shiki):

/components/assistant-ui/shiki-highlighter.tsx
import { createHighlighterCore, createOnigurumaEngine } from "react-shiki/core";

// Create the highlighter
// Use dynamic imports to load languages and themes on client on demand
const customHighlighter = await createHighlighterCore({
  themes: [import("@shikijs/themes/nord")],
  langs: [
    import("@shikijs/langs/javascript"),
    import("@shikijs/langs/typescript"),
  ],
  engine: createOnigurumaEngine(import("shiki/wasm")), 
});

// Then pass it to the highlighter prop
<SyntaxHighlighter
  {...props}
  language={language}
  theme={theme}
  highlighter={customHighlighter}
/>;

For more information, see react-shiki - bundle options.


react-syntax-highlighter

This option may be removed in a future release. Consider using react-shiki instead.

Add syntax-highlighter

npx shadcn@latest add https://r.assistant-ui.com/syntax-highlighter.json

Adds a /components/assistant-ui/syntax-highlighter.tsx file to your project and installs the react-syntax-highlighter dependency.

Add it to defaultComponents in markdown-text.tsx

/components/assistant-ui/markdown-text.tsx
import { SyntaxHighlighter } from "./syntax-highlighter";

export const defaultComponents = memoizeMarkdownComponents({
  SyntaxHighlighter: SyntaxHighlighter,
  h1: /* ... */,
  // ...other elements...
});

Options

Supports all options from react-syntax-highlighter.

Bundle Optimization

By default, the syntax highlighter uses a light build that only includes languages you register. To include all languages:

/components/assistant-ui/syntax-highlighter.tsx
import { makePrismAsyncSyntaxHighlighter } from "@assistant-ui/react-syntax-highlighter/full";
  • Markdown - Rich text rendering that uses syntax highlighting
  • Mermaid - Render diagrams instead of code blocks