# Syntax Highlighting
URL: /docs/ui/syntax-highlighting

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

***

title: Syntax Highlighting
description: Code block syntax highlighting with react-shiki or react-syntax-highlighter.
-----------------------------------------------------------------------------------------

import { InstallCommand } from "@/components/docs/fumadocs/install/install-command";
import { SyntaxHighlightingSample } from "@/components/docs/samples/syntax-highlighting-sample";

<SyntaxHighlightingSample />

<Callout type="warn">Syntax highlighting is not enabled in markdown by default.</Callout>

<Callout type="info">
  `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)
</Callout>

***

## react-shiki

<Steps>
  <Step>
    #### Add `shiki-highlighter`

    <InstallCommand shadcn={["shiki-highlighter"]} />

    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.
  </Step>

  <Step>
    #### Add it to `defaultComponents` in `markdown-text.tsx`

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

    export const defaultComponents = memoizeMarkdownComponents({
      SyntaxHighlighter: SyntaxHighlighter, // [!code ++]
      h1: /* ... */,
      // ...other elements...
    });
    ```
  </Step>
</Steps>

### Options

<TypeTable
  type={Object.fromEntries(
  Object.entries({
    theme: {
      description:
        "Shiki built-in or custom textmate themes. Accepts a single theme or an object of themes mapped to theme mode strings.",
      type: "Theme | Themes",
      typeDescriptionLink:
        "https://github.com/AVGVSTVS96/react-shiki/blob/694433ef697c9791b3816cf94d12d571e8abbb3a/package/src/types.ts#L51",
      default: "github-dark",
      required: true,
    },
    language: {
      description:
        "Shiki built-in or custom textmate grammar object for highlighting",
      type: "Language (string | object)",
      typeDescriptionLink:
        "https://github.com/AVGVSTVS96/react-shiki/blob/694433ef697c9791b3816cf94d12d571e8abbb3a/package/src/types.ts#L24",
      default: "text",
      required: true,
    },
    as: {
      description: "The code block container element type",
      type: "React.ElementType",
      default: "pre",
    },
    className: {
      description: "Custom CSS classes for the code block container element",
      type: "string",
      default: "",
    },
    style: {
      description: "Inline styles for the code block container element",
      type: "React.CSSProperties",
      default: undefined,
    },
    delay: {
      description:
        "Delay in milliseconds between consecutive highlights, useful for streamed code responses.",
      type: "number",
      default: 0,
    },
    customLanguages: {
      description: "Custom languages to preload for highlighting",
      type: "Language[]",
      typeDescriptionLink:
        "https://github.com/AVGVSTVS96/react-shiki/blob/694433ef697c9791b3816cf94d12d571e8abbb3a/package/src/types.ts#L24",
      default: "",
    },
    codeToHastOptions: {
      description: "All other options supported by Shiki's `codeToHast`",
      type: "CodeToHastOptions",
      typeDescriptionLink:
        "https://github.com/shikijs/shiki/blob/main/packages/types/src/options.ts#L121",
      default: "{}",
      required: true,
    },
    // This reverts the order of the type table, fumadocs reversed the order on 4/22/25 in:
    // https://github.com/fuma-nama/fumadocs/commit/3a5595aa65acfa5c20be2377d09c03fbb1de72a6
  }).reverse(),
)}
/>

### 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:

```tsx title="/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):

```tsx title="/components/assistant-ui/shiki-highlighter.tsx" {3-9}
import { createHighlighterCore, createOnigurumaEngine } from "react-shiki/core"; // [!code ++]

// 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} // [!code ++]
/>;
```

<Callout type="info">
  For more information, see [react-shiki - bundle options](https://github.com/avgvstvs96/react-shiki#bundle-options).
</Callout>

### Dual/multi theme support

To use multiple theme modes, pass an object with your multi-theme configuration to the `theme` prop in the `ShikiHighlighter` component:

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

To make themes responsive to your site's theme mode, add one of the following CSS snippets to your project:

```css title="shiki.css"
/* for class based dark mode */
html.dark .shiki,
html.dark .shiki span {
  color: var(--shiki-dark) !important;
  background-color: var(--shiki-dark-bg) !important;
  /* Optional, if you also want font styles */
  font-style: var(--shiki-dark-font-style) !important;
  font-weight: var(--shiki-dark-font-weight) !important;
  text-decoration: var(--shiki-dark-text-decoration) !important;
}

/* for query based dark mode */
@media (prefers-color-scheme: dark) {
  .shiki,
  .shiki span {
    color: var(--shiki-dark) !important;
    background-color: var(--shiki-dark-bg) !important;
    /* Optional, if you also want font styles */
    font-style: var(--shiki-dark-font-style) !important;
    font-weight: var(--shiki-dark-font-weight) !important;
    text-decoration: var(--shiki-dark-text-decoration) !important;
  }
}
```

For more information, see [Shiki's documentation on dual and multi themes](https://shiki.style/guide/dual-themes).

***

## react-syntax-highlighter

<Callout type="warn">
  This option may be removed in a future release. Consider using
  [react-shiki](#react-shiki) instead.
</Callout>

<Steps>
  <Step>
    #### Add `syntax-highlighter`

    <InstallCommand shadcn={["syntax-highlighter"]} />

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

  <Step>
    #### Add it to `defaultComponents` in `markdown-text.tsx`

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

    export const defaultComponents = memoizeMarkdownComponents({
      SyntaxHighlighter: SyntaxHighlighter, // [!code ++]
      h1: /* ... */,
      // ...other elements...
    });
    ```
  </Step>
</Steps>

### Options

Supports all options from [`react-syntax-highlighter`](https://github.com/react-syntax-highlighter/react-syntax-highlighter#props).

### Bundle Optimization

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

```tsx title="/components/assistant-ui/syntax-highlighter.tsx"
import { makePrismAsyncSyntaxHighlighter } from "@assistant-ui/react-syntax-highlighter/full";
```

## Related Components

* [Markdown](/docs/ui/markdown) - Rich text rendering that uses syntax highlighting
* [Mermaid](/docs/ui/mermaid) - Render diagrams instead of code blocks
