Docs
Quick start

Quick start


Setup llm-ui with code and markdown blocks:

## Python

```python
print('Hello llm-ui!')
```

## Typescript

```typescript
console.log('Hello llm-ui!');
```

1x

Install dependencies

pnpm add @llm-ui/react @llm-ui/markdown react-markdown remark-gfm @llm-ui/code shiki html-react-parser

Setup

View on GitHub

Step 1: Create a markdown component

Create a component to render markdown using react-markdown.

import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { type LLMOutputComponent } from "@llm-ui/react";


// Customize this component with your own styling
const MarkdownComponent: LLMOutputComponent = ({ blockMatch }) => {
  const markdown = blockMatch.output;
  return <ReactMarkdown remarkPlugins={[remarkGfm]}>{markdown}</ReactMarkdown>;
};

Read more in the markdown block docs

Step 2: Create a code block component

Create a component to render code blocks using Shiki.

import type { CodeToHtmlOptions } from "@llm-ui/code";
import {
  loadHighlighter,
  useCodeBlockToHtml,
  allLangs,
  allLangsAlias,
} from "@llm-ui/code";
// WARNING: Importing bundledThemes increases your bundle size
// see: https://llm-ui.com/docs/blocks/code#bundle-size
import { bundledThemes } from "shiki/themes";
import { type LLMOutputComponent } from "@llm-ui/react";
import parseHtml from "html-react-parser";
import { getHighlighterCore } from "shiki/core";
import { bundledLanguagesInfo } from "shiki/langs";

import getWasm from "shiki/wasm";

const highlighter = loadHighlighter(
  getHighlighterCore({
    langs: allLangs(bundledLanguagesInfo),
    langAlias: allLangsAlias(bundledLanguagesInfo),
    themes: Object.values(bundledThemes),
    loadWasm: getWasm,
  }),
);

const codeToHtmlOptions: CodeToHtmlOptions = {
  theme: "github-dark",
};

// Customize this component with your own styling
const CodeBlock: LLMOutputComponent = ({ blockMatch }) => {
  const { html, code } = useCodeBlockToHtml({
    markdownCodeBlock: blockMatch.output,
    highlighter,
    codeToHtmlOptions,
  });
  if (!html) {
    // fallback to <pre> if Shiki is not loaded yet
    return (
      <pre className="shiki">
        <code>{code}</code>
      </pre>
    );
  }
  return <>{parseHtml(html)}</>;
};

Read more in the code block docs

Step 3: Render markdown and code with llm-ui

Now we’ve created our components, we’re ready to use useLLMOutput to render language model output which contains markdown and code.

import {
  codeBlockLookBack,
  findCompleteCodeBlock,
  findPartialCodeBlock,
} from "@llm-ui/code";
import { markdownLookBack } from "@llm-ui/markdown";
import { useLLMOutput, useStreamExample } from "@llm-ui/react";

const example = `## Python

\`\`\`python
print('Hello llm-ui!')
\`\`\`
...continues...
`;

const Example = () => {
  const { isStreamFinished, output } = useStreamExample(example);

  const { blockMatches } = useLLMOutput({
    llmOutput: output,
    fallbackBlock: {
      component: MarkdownComponent, // from Step 1
      lookBack: markdownLookBack(),
    },
    blocks: [
      {
        component: CodeBlock, // from Step 2
        findCompleteMatch: findCompleteCodeBlock(),
        findPartialMatch: findPartialCodeBlock(),
        lookBack: codeBlockLookBack(),
      },
    ],
    isStreamFinished,
  });

  return (
    <div>
      {blockMatches.map((blockMatch, index) => {
        const Component = blockMatch.block.component;
        return <Component key={index} blockMatch={blockMatch} />;
      })}
    </div>
  );
};

Read more in the useLLMOutput docs

Setting up Shiki with Next.js

To use shiki client-side with next.js you must use dynamic imports to avoid server-side-rendering.

// file: app/page.tsx

import dynamic from "next/dynamic";

const Page = () => {
  // Code which uses Shiki for code highlighting must be imported dynamically
  const Example = dynamic(() => import("./example"), { ssr: false });
  return <Example />;
};

export default Page;

Read more about setting up Shiki in the code block docs.