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