diff --git a/.changeset/eleven-monkeys-yell.md b/.changeset/eleven-monkeys-yell.md
new file mode 100644
index 00000000..c9bfe5bc
--- /dev/null
+++ b/.changeset/eleven-monkeys-yell.md
@@ -0,0 +1,5 @@
+---
+"@llm-ui/custom": patch
+---
+
+update @llm-ui/custom readme
diff --git a/examples/code/nextjs/package.json b/examples/code/nextjs/package.json
index 0875d671..9ea99402 100644
--- a/examples/code/nextjs/package.json
+++ b/examples/code/nextjs/package.json
@@ -10,9 +10,9 @@
"lint": "next lint"
},
"dependencies": {
- "@llm-ui/code": "^0.4.0",
- "@llm-ui/markdown": "^0.4.0",
- "@llm-ui/react": "^0.4.0",
+ "@llm-ui/code": "^0.6.0",
+ "@llm-ui/markdown": "^0.6.0",
+ "@llm-ui/react": "^0.6.0",
"html-react-parser": "^5.1.10",
"next": "14.2.3",
"react": "^18",
diff --git a/examples/code/vite/package.json b/examples/code/vite/package.json
index 2952125f..176c7256 100644
--- a/examples/code/vite/package.json
+++ b/examples/code/vite/package.json
@@ -11,9 +11,9 @@
"preview": "vite preview"
},
"dependencies": {
- "@llm-ui/code": "^0.4.0",
- "@llm-ui/markdown": "^0.4.0",
- "@llm-ui/react": "^0.4.0",
+ "@llm-ui/code": "^0.6.0",
+ "@llm-ui/markdown": "^0.6.0",
+ "@llm-ui/react": "^0.6.0",
"html-react-parser": "^5.1.10",
"react": "^18.2.0",
"react-dom": "^18.2.0",
diff --git a/examples/custom-components/nextjs/.eslintrc.json b/examples/custom-components/nextjs/.eslintrc.json
new file mode 100644
index 00000000..bffb357a
--- /dev/null
+++ b/examples/custom-components/nextjs/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "next/core-web-vitals"
+}
diff --git a/examples/custom-components/nextjs/.gitignore b/examples/custom-components/nextjs/.gitignore
new file mode 100644
index 00000000..8127a9b2
--- /dev/null
+++ b/examples/custom-components/nextjs/.gitignore
@@ -0,0 +1,39 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+.yarn/install-state.gz
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
+
+
+.env
diff --git a/examples/custom-components/nextjs/README.md b/examples/custom-components/nextjs/README.md
new file mode 100644
index 00000000..d3f20d2e
--- /dev/null
+++ b/examples/custom-components/nextjs/README.md
@@ -0,0 +1,21 @@
+# Custom block example (Next.js)
+
+## How to use
+
+Execute create-llm-ui with pnpm, npm, bun, or yarn to setup the example:
+
+```bash
+pnpx create-llm-ui example custom-components/nextjs llm-ui-custom-components-nextjs-example
+```
+
+```bash
+npx create-llm-ui example custom-components/nextjs llm-ui-custom-components-nextjs-example
+```
+
+```bash
+bunx create-llm-ui example custom-components/nextjs llm-ui-custom-components-nextjs-example
+```
+
+```bash
+yarn create llm-ui example custom-components/nextjs llm-ui-custom-components-nextjs-example
+```
diff --git a/examples/custom-components/nextjs/next.config.mjs b/examples/custom-components/nextjs/next.config.mjs
new file mode 100644
index 00000000..4678774e
--- /dev/null
+++ b/examples/custom-components/nextjs/next.config.mjs
@@ -0,0 +1,4 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {};
+
+export default nextConfig;
diff --git a/examples/custom-components/nextjs/package.json b/examples/custom-components/nextjs/package.json
new file mode 100644
index 00000000..f8d440ff
--- /dev/null
+++ b/examples/custom-components/nextjs/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "llm-ui-custom-components-nextjs-example",
+ "license": "MIT",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint"
+ },
+ "dependencies": {
+ "@llm-ui/custom": "^0.6.0",
+ "@llm-ui/markdown": "^0.6.0",
+ "@llm-ui/react": "^0.6.0",
+ "next": "14.2.3",
+ "react": "^18",
+ "react-dom": "^18",
+ "react-markdown": "^9.0.1",
+ "remark-gfm": "^4.0.0",
+ "zod": "^3.23.8"
+ },
+ "devDependencies": {
+ "@tailwindcss/typography": "^0.5.13",
+ "@types/node": "^20",
+ "@types/react": "^18",
+ "@types/react-dom": "^18",
+ "eslint": "^8",
+ "eslint-config-next": "14.2.3",
+ "postcss": "^8",
+ "tailwindcss": "^3.4.1",
+ "typescript": "^5"
+ }
+}
diff --git a/examples/custom-components/nextjs/postcss.config.mjs b/examples/custom-components/nextjs/postcss.config.mjs
new file mode 100644
index 00000000..1a69fd2a
--- /dev/null
+++ b/examples/custom-components/nextjs/postcss.config.mjs
@@ -0,0 +1,8 @@
+/** @type {import('postcss-load-config').Config} */
+const config = {
+ plugins: {
+ tailwindcss: {},
+ },
+};
+
+export default config;
diff --git a/examples/custom-components/nextjs/src/app/globals.css b/examples/custom-components/nextjs/src/app/globals.css
new file mode 100644
index 00000000..f79984ce
--- /dev/null
+++ b/examples/custom-components/nextjs/src/app/globals.css
@@ -0,0 +1,39 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+body {
+ @apply text-white;
+ @apply bg-gray-950;
+}
+
+@layer utilities {
+ .text-balance {
+ text-wrap: balance;
+ }
+}
+
+button {
+ @apply mr-4 rounded bg-blue-500 px-4 py-2 font-semibold text-white;
+}
+
+a {
+ @apply underline underline-offset-4;
+}
+
+pre {
+ @apply p-4;
+ @apply rounded-lg;
+ @apply overflow-x-auto;
+ @apply border;
+ @apply border-gray-800;
+ background-color: black !important;
+}
+
+.markdown {
+ @apply prose prose-invert;
+}
+
+body > div {
+ @apply m-8 mx-auto max-w-screen-md rounded-lg bg-black p-8 pt-1;
+}
diff --git a/examples/custom-components/nextjs/src/app/layout.tsx b/examples/custom-components/nextjs/src/app/layout.tsx
new file mode 100644
index 00000000..d960847c
--- /dev/null
+++ b/examples/custom-components/nextjs/src/app/layout.tsx
@@ -0,0 +1,22 @@
+import type { Metadata } from "next";
+import { Inter } from "next/font/google";
+import "./globals.css";
+
+const inter = Inter({ subsets: ["latin"] });
+
+export const metadata: Metadata = {
+ title: "llm-ui-custom-components-nextjs-example",
+ description: "llm-ui-custom-components-nextjs-example",
+};
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ return (
+
+
{children}
+
+ );
+}
diff --git a/examples/custom-components/nextjs/src/app/page.tsx b/examples/custom-components/nextjs/src/app/page.tsx
new file mode 100644
index 00000000..e783e11a
--- /dev/null
+++ b/examples/custom-components/nextjs/src/app/page.tsx
@@ -0,0 +1,87 @@
+"use client";
+import { customBlock, parseJson5 } from "@llm-ui/custom";
+import { markdownLookBack } from "@llm-ui/markdown";
+import {
+ useLLMOutput,
+ useStreamExample,
+ type LLMOutputComponent,
+} from "@llm-ui/react";
+
+import ReactMarkdown from "react-markdown";
+import remarkGfm from "remark-gfm";
+import z from "zod";
+
+const buttonsSchema = z.object({
+ t: z.literal("btn"),
+ btns: z.array(z.object({ text: z.string() })),
+});
+
+const buttonsPartialSchema = buttonsSchema.deepPartial();
+
+// -------Step 1: Create a markdown component-------
+
+// Customize this component with your own styling
+const MarkdownComponent: LLMOutputComponent = ({ blockMatch }) => {
+ const markdown = blockMatch.output;
+ return (
+
+ {markdown}
+
+ );
+};
+
+// -------Step 2: Create a buttons component-------
+
+// Customize this component with your own styling
+const ButtonsComponent: LLMOutputComponent = ({ blockMatch }) => {
+ const buttons = buttonsPartialSchema.parse(parseJson5(blockMatch.output));
+ if (!buttons) {
+ return undefined;
+ }
+ return (
+
+ {buttons?.btns?.map(
+ (button, index) =>
+ button?.text && ,
+ )}
+
+ );
+};
+
+// -------Step 3: Render markdown with llm-ui-------
+
+const example = `
+## Example
+
+【{t:"btn",btns:[{text:"Button 1"}, {text:"Button 2"}]}】
+`;
+
+const Example = () => {
+ const { isStreamFinished, output } = useStreamExample(example);
+
+ const { blockMatches } = useLLMOutput({
+ llmOutput: output,
+ blocks: [
+ {
+ ...customBlock("btn"),
+ component: ButtonsComponent,
+ },
+ ],
+ fallbackBlock: {
+ component: MarkdownComponent,
+ lookBack: markdownLookBack(),
+ },
+ isStreamFinished,
+ });
+
+ return (
+
+ {blockMatches.map((blockMatch, index) => {
+ const Component = blockMatch.block.component;
+ return ;
+ })}
+
+ );
+};
+
+export default Example;
diff --git a/examples/custom-components/nextjs/tailwind.config.ts b/examples/custom-components/nextjs/tailwind.config.ts
new file mode 100644
index 00000000..4c84816f
--- /dev/null
+++ b/examples/custom-components/nextjs/tailwind.config.ts
@@ -0,0 +1,21 @@
+import typography from "@tailwindcss/typography";
+import type { Config } from "tailwindcss";
+
+const config: Config = {
+ content: [
+ "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
+ "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
+ "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
+ ],
+ theme: {
+ extend: {
+ backgroundImage: {
+ "gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
+ "gradient-conic":
+ "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
+ },
+ },
+ },
+ plugins: [typography],
+};
+export default config;
diff --git a/examples/custom-components/nextjs/tsconfig.json b/examples/custom-components/nextjs/tsconfig.json
new file mode 100644
index 00000000..7b285893
--- /dev/null
+++ b/examples/custom-components/nextjs/tsconfig.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+ "exclude": ["node_modules"]
+}
diff --git a/examples/custom-components/vite/.eslintrc.cjs b/examples/custom-components/vite/.eslintrc.cjs
new file mode 100644
index 00000000..6e8698b7
--- /dev/null
+++ b/examples/custom-components/vite/.eslintrc.cjs
@@ -0,0 +1,18 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:react-hooks/recommended",
+ ],
+ ignorePatterns: ["dist", ".eslintrc.cjs"],
+ parser: "@typescript-eslint/parser",
+ plugins: ["react-refresh"],
+ rules: {
+ "react-refresh/only-export-components": [
+ "warn",
+ { allowConstantExport: true },
+ ],
+ },
+};
diff --git a/examples/custom-components/vite/.gitignore b/examples/custom-components/vite/.gitignore
new file mode 100644
index 00000000..ae029d6b
--- /dev/null
+++ b/examples/custom-components/vite/.gitignore
@@ -0,0 +1,27 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+
+
+.env
diff --git a/examples/custom-components/vite/README.md b/examples/custom-components/vite/README.md
new file mode 100644
index 00000000..54dc54f1
--- /dev/null
+++ b/examples/custom-components/vite/README.md
@@ -0,0 +1,21 @@
+# Custom block example (Vite)
+
+## How to use
+
+Execute create-llm-ui with pnpm, npm, bun, or yarn to setup the example:
+
+```bash
+pnpx create-llm-ui example custom-components/vite llm-ui-custom-components-vite-example
+```
+
+```bash
+npx create-llm-ui example custom-components/vite llm-ui-custom-components-vite-example
+```
+
+```bash
+bunx create-llm-ui example custom-components/vite llm-ui-custom-components-vite-example
+```
+
+```bash
+yarn create llm-ui example custom-components/vite llm-ui-custom-components-vite-example
+```
diff --git a/examples/custom-components/vite/index.html b/examples/custom-components/vite/index.html
new file mode 100644
index 00000000..75b101fe
--- /dev/null
+++ b/examples/custom-components/vite/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Custom block example (Vite)
+
+
+
+
+
+
diff --git a/examples/custom-components/vite/package.json b/examples/custom-components/vite/package.json
new file mode 100644
index 00000000..734799dc
--- /dev/null
+++ b/examples/custom-components/vite/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "llm-ui-custom-components-vite-example",
+ "license": "MIT",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@llm-ui/custom": "^0.6.0",
+ "@llm-ui/markdown": "^0.6.0",
+ "@llm-ui/react": "^0.6.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-markdown": "^9.0.1",
+ "remark-gfm": "^4.0.0",
+ "zod": "^3.23.8"
+ },
+ "devDependencies": {
+ "@tailwindcss/typography": "^0.5.13",
+ "@types/react": "^18.2.66",
+ "@types/react-dom": "^18.2.22",
+ "@typescript-eslint/eslint-plugin": "^7.2.0",
+ "@typescript-eslint/parser": "^7.2.0",
+ "@vitejs/plugin-react": "^4.2.1",
+ "autoprefixer": "^10.4.19",
+ "eslint": "^8.57.0",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.6",
+ "postcss": "^8.4.38",
+ "tailwindcss": "^3.4.3",
+ "typescript": "^5.2.2",
+ "vite": "^5.2.0"
+ }
+}
diff --git a/examples/custom-components/vite/postcss.config.js b/examples/custom-components/vite/postcss.config.js
new file mode 100644
index 00000000..2aa7205d
--- /dev/null
+++ b/examples/custom-components/vite/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/examples/custom-components/vite/public/vite.svg b/examples/custom-components/vite/public/vite.svg
new file mode 100644
index 00000000..e7b8dfb1
--- /dev/null
+++ b/examples/custom-components/vite/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/examples/custom-components/vite/src/App.tsx b/examples/custom-components/vite/src/App.tsx
new file mode 100644
index 00000000..e783e11a
--- /dev/null
+++ b/examples/custom-components/vite/src/App.tsx
@@ -0,0 +1,87 @@
+"use client";
+import { customBlock, parseJson5 } from "@llm-ui/custom";
+import { markdownLookBack } from "@llm-ui/markdown";
+import {
+ useLLMOutput,
+ useStreamExample,
+ type LLMOutputComponent,
+} from "@llm-ui/react";
+
+import ReactMarkdown from "react-markdown";
+import remarkGfm from "remark-gfm";
+import z from "zod";
+
+const buttonsSchema = z.object({
+ t: z.literal("btn"),
+ btns: z.array(z.object({ text: z.string() })),
+});
+
+const buttonsPartialSchema = buttonsSchema.deepPartial();
+
+// -------Step 1: Create a markdown component-------
+
+// Customize this component with your own styling
+const MarkdownComponent: LLMOutputComponent = ({ blockMatch }) => {
+ const markdown = blockMatch.output;
+ return (
+
+ {markdown}
+
+ );
+};
+
+// -------Step 2: Create a buttons component-------
+
+// Customize this component with your own styling
+const ButtonsComponent: LLMOutputComponent = ({ blockMatch }) => {
+ const buttons = buttonsPartialSchema.parse(parseJson5(blockMatch.output));
+ if (!buttons) {
+ return undefined;
+ }
+ return (
+
+ {buttons?.btns?.map(
+ (button, index) =>
+ button?.text && ,
+ )}
+
+ );
+};
+
+// -------Step 3: Render markdown with llm-ui-------
+
+const example = `
+## Example
+
+【{t:"btn",btns:[{text:"Button 1"}, {text:"Button 2"}]}】
+`;
+
+const Example = () => {
+ const { isStreamFinished, output } = useStreamExample(example);
+
+ const { blockMatches } = useLLMOutput({
+ llmOutput: output,
+ blocks: [
+ {
+ ...customBlock("btn"),
+ component: ButtonsComponent,
+ },
+ ],
+ fallbackBlock: {
+ component: MarkdownComponent,
+ lookBack: markdownLookBack(),
+ },
+ isStreamFinished,
+ });
+
+ return (
+
+ {blockMatches.map((blockMatch, index) => {
+ const Component = blockMatch.block.component;
+ return ;
+ })}
+
+ );
+};
+
+export default Example;
diff --git a/examples/custom-components/vite/src/assets/react.svg b/examples/custom-components/vite/src/assets/react.svg
new file mode 100644
index 00000000..6c87de9b
--- /dev/null
+++ b/examples/custom-components/vite/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/examples/custom-components/vite/src/index.css b/examples/custom-components/vite/src/index.css
new file mode 100644
index 00000000..f79984ce
--- /dev/null
+++ b/examples/custom-components/vite/src/index.css
@@ -0,0 +1,39 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+body {
+ @apply text-white;
+ @apply bg-gray-950;
+}
+
+@layer utilities {
+ .text-balance {
+ text-wrap: balance;
+ }
+}
+
+button {
+ @apply mr-4 rounded bg-blue-500 px-4 py-2 font-semibold text-white;
+}
+
+a {
+ @apply underline underline-offset-4;
+}
+
+pre {
+ @apply p-4;
+ @apply rounded-lg;
+ @apply overflow-x-auto;
+ @apply border;
+ @apply border-gray-800;
+ background-color: black !important;
+}
+
+.markdown {
+ @apply prose prose-invert;
+}
+
+body > div {
+ @apply m-8 mx-auto max-w-screen-md rounded-lg bg-black p-8 pt-1;
+}
diff --git a/examples/custom-components/vite/src/main.tsx b/examples/custom-components/vite/src/main.tsx
new file mode 100644
index 00000000..f25366e5
--- /dev/null
+++ b/examples/custom-components/vite/src/main.tsx
@@ -0,0 +1,10 @@
+import React from "react";
+import ReactDOM from "react-dom/client";
+import App from "./App.tsx";
+import "./index.css";
+
+ReactDOM.createRoot(document.getElementById("root")!).render(
+
+
+ ,
+);
diff --git a/examples/custom-components/vite/src/vite-env.d.ts b/examples/custom-components/vite/src/vite-env.d.ts
new file mode 100644
index 00000000..11f02fe2
--- /dev/null
+++ b/examples/custom-components/vite/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/examples/custom-components/vite/tailwind.config.ts b/examples/custom-components/vite/tailwind.config.ts
new file mode 100644
index 00000000..98f26cc9
--- /dev/null
+++ b/examples/custom-components/vite/tailwind.config.ts
@@ -0,0 +1,10 @@
+import typography from "@tailwindcss/typography";
+import type { Config } from "tailwindcss";
+
+export default {
+ content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
+ theme: {
+ extend: {},
+ },
+ plugins: [typography],
+} satisfies Config;
diff --git a/examples/custom-components/vite/tsconfig.json b/examples/custom-components/vite/tsconfig.json
new file mode 100644
index 00000000..a7fc6fbf
--- /dev/null
+++ b/examples/custom-components/vite/tsconfig.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/examples/custom-components/vite/tsconfig.node.json b/examples/custom-components/vite/tsconfig.node.json
new file mode 100644
index 00000000..97ede7ee
--- /dev/null
+++ b/examples/custom-components/vite/tsconfig.node.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/examples/custom-components/vite/vite.config.ts b/examples/custom-components/vite/vite.config.ts
new file mode 100644
index 00000000..1ff0da0a
--- /dev/null
+++ b/examples/custom-components/vite/vite.config.ts
@@ -0,0 +1,7 @@
+import react from "@vitejs/plugin-react";
+import { defineConfig } from "vite";
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+});
diff --git a/examples/markdown/nextjs/package.json b/examples/markdown/nextjs/package.json
index 21562719..81341b2b 100644
--- a/examples/markdown/nextjs/package.json
+++ b/examples/markdown/nextjs/package.json
@@ -10,8 +10,8 @@
"lint": "next lint"
},
"dependencies": {
- "@llm-ui/markdown": "^0.4.0",
- "@llm-ui/react": "^0.4.0",
+ "@llm-ui/markdown": "^0.6.0",
+ "@llm-ui/react": "^0.6.0",
"next": "14.2.3",
"react": "^18",
"react-dom": "^18",
diff --git a/examples/markdown/vite/package.json b/examples/markdown/vite/package.json
index 748528e9..ed9a6e20 100644
--- a/examples/markdown/vite/package.json
+++ b/examples/markdown/vite/package.json
@@ -11,8 +11,8 @@
"preview": "vite preview"
},
"dependencies": {
- "@llm-ui/markdown": "^0.4.0",
- "@llm-ui/react": "^0.4.0",
+ "@llm-ui/markdown": "^0.6.0",
+ "@llm-ui/react": "^0.6.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-markdown": "^9.0.1",
diff --git a/examples/openai/nextjs/package.json b/examples/openai/nextjs/package.json
index 4896189d..880aa976 100644
--- a/examples/openai/nextjs/package.json
+++ b/examples/openai/nextjs/package.json
@@ -10,9 +10,9 @@
"lint": "next lint"
},
"dependencies": {
- "@llm-ui/code": "^0.4.0",
- "@llm-ui/markdown": "^0.4.0",
- "@llm-ui/react": "^0.4.0",
+ "@llm-ui/code": "^0.6.0",
+ "@llm-ui/markdown": "^0.6.0",
+ "@llm-ui/react": "^0.6.0",
"html-react-parser": "^5.1.10",
"next": "14.2.3",
"openai": "^4.47.1",
diff --git a/examples/openai/vite-and-express/package.json b/examples/openai/vite-and-express/package.json
index 4d9d5b5c..938e2a8e 100644
--- a/examples/openai/vite-and-express/package.json
+++ b/examples/openai/vite-and-express/package.json
@@ -11,9 +11,9 @@
"preview": "vite preview"
},
"dependencies": {
- "@llm-ui/code": "^0.4.0",
- "@llm-ui/markdown": "^0.4.0",
- "@llm-ui/react": "^0.4.0",
+ "@llm-ui/code": "^0.6.0",
+ "@llm-ui/markdown": "^0.6.0",
+ "@llm-ui/react": "^0.6.0",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"html-react-parser": "^5.1.10",
diff --git a/examples/vercel-ai/nextjs/package.json b/examples/vercel-ai/nextjs/package.json
index ba82a382..1c00612a 100644
--- a/examples/vercel-ai/nextjs/package.json
+++ b/examples/vercel-ai/nextjs/package.json
@@ -11,9 +11,9 @@
},
"dependencies": {
"@ai-sdk/openai": "^0.0.14",
- "@llm-ui/code": "^0.4.0",
- "@llm-ui/markdown": "^0.4.0",
- "@llm-ui/react": "^0.4.0",
+ "@llm-ui/code": "^0.6.0",
+ "@llm-ui/markdown": "^0.6.0",
+ "@llm-ui/react": "^0.6.0",
"ai": "^3.1.13",
"html-react-parser": "^5.1.10",
"next": "14.2.3",
diff --git a/packages/custom/README.md b/packages/custom/README.md
new file mode 100644
index 00000000..5c72b33e
--- /dev/null
+++ b/packages/custom/README.md
@@ -0,0 +1,5 @@
+# @llm-ui/custom
+
+[llm-ui](https://llm-ui.com) custom blocks.
+
+Documentation: https://llm-ui.com/docs/custom-blocks
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a562b762..bcf014e2 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -277,14 +277,14 @@ importers:
examples/code/nextjs:
dependencies:
'@llm-ui/code':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)(shiki@1.6.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/code
'@llm-ui/markdown':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/markdown
'@llm-ui/react':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/react
html-react-parser:
specifier: ^5.1.10
version: 5.1.10(@types/react@18.2.73)(react@18.2.0)
@@ -338,14 +338,14 @@ importers:
examples/code/vite:
dependencies:
'@llm-ui/code':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)(shiki@1.6.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/code
'@llm-ui/markdown':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/markdown
'@llm-ui/react':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/react
html-react-parser:
specifier: ^5.1.10
version: 5.1.10(@types/react@18.2.73)(react@18.2.0)
@@ -408,14 +408,142 @@ importers:
specifier: ^5.2.0
version: 5.2.7
+ examples/custom-components/nextjs:
+ dependencies:
+ '@llm-ui/custom':
+ specifier: ^0.6.0
+ version: link:../../../packages/custom
+ '@llm-ui/markdown':
+ specifier: ^0.6.0
+ version: link:../../../packages/markdown
+ '@llm-ui/react':
+ specifier: ^0.6.0
+ version: link:../../../packages/react
+ next:
+ specifier: 14.2.3
+ version: 14.2.3(react-dom@18.2.0)(react@18.2.0)
+ react:
+ specifier: ^18
+ version: 18.2.0
+ react-dom:
+ specifier: ^18
+ version: 18.2.0(react@18.2.0)
+ react-markdown:
+ specifier: ^9.0.1
+ version: 9.0.1(@types/react@18.2.73)(react@18.2.0)
+ remark-gfm:
+ specifier: ^4.0.0
+ version: 4.0.0
+ zod:
+ specifier: ^3.23.8
+ version: 3.23.8
+ devDependencies:
+ '@tailwindcss/typography':
+ specifier: ^0.5.13
+ version: 0.5.13(tailwindcss@3.4.3)
+ '@types/node':
+ specifier: ^20
+ version: 20.12.7
+ '@types/react':
+ specifier: ^18
+ version: 18.2.73
+ '@types/react-dom':
+ specifier: ^18
+ version: 18.2.23
+ eslint:
+ specifier: ^8
+ version: 8.57.0
+ eslint-config-next:
+ specifier: 14.2.3
+ version: 14.2.3(eslint@8.57.0)(typescript@5.4.3)
+ postcss:
+ specifier: ^8
+ version: 8.4.38
+ tailwindcss:
+ specifier: ^3.4.1
+ version: 3.4.3
+ typescript:
+ specifier: ^5
+ version: 5.4.3
+
+ examples/custom-components/vite:
+ dependencies:
+ '@llm-ui/custom':
+ specifier: ^0.6.0
+ version: link:../../../packages/custom
+ '@llm-ui/markdown':
+ specifier: ^0.6.0
+ version: link:../../../packages/markdown
+ '@llm-ui/react':
+ specifier: ^0.6.0
+ version: link:../../../packages/react
+ react:
+ specifier: ^18.2.0
+ version: 18.2.0
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.2.0(react@18.2.0)
+ react-markdown:
+ specifier: ^9.0.1
+ version: 9.0.1(@types/react@18.2.73)(react@18.2.0)
+ remark-gfm:
+ specifier: ^4.0.0
+ version: 4.0.0
+ zod:
+ specifier: ^3.23.8
+ version: 3.23.8
+ devDependencies:
+ '@tailwindcss/typography':
+ specifier: ^0.5.13
+ version: 0.5.13(tailwindcss@3.4.3)
+ '@types/react':
+ specifier: ^18.2.66
+ version: 18.2.73
+ '@types/react-dom':
+ specifier: ^18.2.22
+ version: 18.2.23
+ '@typescript-eslint/eslint-plugin':
+ specifier: ^7.2.0
+ version: 7.4.0(@typescript-eslint/parser@7.4.0)(eslint@8.57.0)(typescript@5.4.3)
+ '@typescript-eslint/parser':
+ specifier: ^7.2.0
+ version: 7.4.0(eslint@8.57.0)(typescript@5.4.3)
+ '@vitejs/plugin-react':
+ specifier: ^4.2.1
+ version: 4.2.1(vite@5.2.7)
+ autoprefixer:
+ specifier: ^10.4.19
+ version: 10.4.19(postcss@8.4.38)
+ eslint:
+ specifier: ^8.57.0
+ version: 8.57.0
+ eslint-plugin-react-hooks:
+ specifier: ^4.6.0
+ version: 4.6.0(eslint@8.57.0)
+ eslint-plugin-react-refresh:
+ specifier: ^0.4.6
+ version: 0.4.7(eslint@8.57.0)
+ postcss:
+ specifier: ^8.4.38
+ version: 8.4.38
+ tailwindcss:
+ specifier: ^3.4.3
+ version: 3.4.3
+ typescript:
+ specifier: ^5.2.2
+ version: 5.4.3
+ vite:
+ specifier: ^5.2.0
+ version: 5.2.7
+
examples/markdown/nextjs:
dependencies:
'@llm-ui/markdown':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/markdown
'@llm-ui/react':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/react
next:
specifier: 14.2.3
version: 14.2.3(react-dom@18.2.0)(react@18.2.0)
@@ -463,11 +591,11 @@ importers:
examples/markdown/vite:
dependencies:
'@llm-ui/markdown':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/markdown
'@llm-ui/react':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/react
react:
specifier: ^18.2.0
version: 18.2.0
@@ -527,14 +655,14 @@ importers:
examples/openai/nextjs:
dependencies:
'@llm-ui/code':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)(shiki@1.6.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/code
'@llm-ui/markdown':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/markdown
'@llm-ui/react':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/react
html-react-parser:
specifier: ^5.1.10
version: 5.1.10(@types/react@18.2.73)(react@18.2.0)
@@ -591,14 +719,14 @@ importers:
examples/openai/vite-and-express:
dependencies:
'@llm-ui/code':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)(shiki@1.6.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/code
'@llm-ui/markdown':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/markdown
'@llm-ui/react':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/react
dotenv:
specifier: ^16.4.5
version: 16.4.5
@@ -685,14 +813,14 @@ importers:
specifier: ^0.0.14
version: 0.0.14(zod@3.23.8)
'@llm-ui/code':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)(shiki@1.6.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/code
'@llm-ui/markdown':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/markdown
'@llm-ui/react':
- specifier: ^0.4.0
- version: 0.4.0(react@18.2.0)
+ specifier: ^0.6.0
+ version: link:../../../packages/react
ai:
specifier: ^3.1.13
version: 3.1.13(react@18.2.0)(solid-js@1.8.17)(svelte@4.2.17)(vue@3.4.27)(zod@3.23.8)
@@ -2686,52 +2814,6 @@ packages:
dev: false
optional: true
- /@llm-ui/code@0.4.0(react@18.2.0)(shiki@1.6.0):
- resolution: {integrity: sha512-5dpBZstatzKeMxcJz4JR5+on0asP0Q24pl5N9p/9cH4fIghavhVUa2cBDYJGZ149EMSTEEjM8dtsUQW8ssol7Q==}
- peerDependencies:
- react: ^18.0.0
- shiki: ^1.5.2
- dependencies:
- '@llm-ui/react': 0.4.0(react@18.2.0)
- '@llm-ui/shared': 0.4.0(react@18.2.0)
- react: 18.2.0
- shiki: 1.6.0
- dev: false
-
- /@llm-ui/markdown@0.4.0(react@18.2.0):
- resolution: {integrity: sha512-5v9sGReSr7MjT9kZk921zrlET7srT3eJ26eavtJfHJN7v1cEa/WSanpxRswv5jZig1SSpbLd5Gy47CtxGLYvQA==}
- peerDependencies:
- react: ^18.0.0
- dependencies:
- '@llm-ui/react': 0.4.0(react@18.2.0)
- mdast-util-from-markdown: 2.0.0
- mdast-util-gfm: 3.0.0
- mdast-util-to-markdown: 2.1.0
- micromark-extension-gfm: 3.0.0
- react: 18.2.0
- remeda: 1.57.0
- unist-util-visit: 5.0.0
- transitivePeerDependencies:
- - supports-color
- dev: false
-
- /@llm-ui/react@0.4.0(react@18.2.0):
- resolution: {integrity: sha512-tgjo/bd9kNvWAk4TzYW2cLCD4u2VenmMX/DJsOwkbLaitpfIo6IOTF1wpM+DBJkmuOOGNqepuUAT6++0XIUq1A==}
- peerDependencies:
- react: ^18.0.0
- dependencies:
- react: 18.2.0
- remeda: 1.57.0
- dev: false
-
- /@llm-ui/shared@0.4.0(react@18.2.0):
- resolution: {integrity: sha512-tqaVGTS1kfo/wFJJobaMlK1FZu4Khe7IjGowmJTYER3vKCe8ejNOakuTFSe9i/Pjb4qdVZm1V0FkajhJzoEJzg==}
- dependencies:
- '@llm-ui/react': 0.4.0(react@18.2.0)
- transitivePeerDependencies:
- - react
- dev: false
-
/@manypkg/find-root@1.1.0:
resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==}
dependencies:
diff --git a/tooling/examples/src/examples.ts b/tooling/examples/src/examples.ts
index f55fb9cb..dd6a64ea 100644
--- a/tooling/examples/src/examples.ts
+++ b/tooling/examples/src/examples.ts
@@ -1,5 +1,5 @@
import { codeNextJs, codeVite } from "./code";
-// import { customNextJs, customVite } from "./custom";
+import { customNextJs, customVite } from "./custom";
import { markdownNextJs, markdownVite } from "./markdown";
import { openaiNextJs, openaiVite } from "./openai";
import { vercelAiNextJs } from "./vercel-ai";
@@ -8,8 +8,8 @@ export const examples = [
vercelAiNextJs,
markdownNextJs,
markdownVite,
- // customNextJs,
- // customVite,
+ customNextJs,
+ customVite,
codeNextJs,
codeVite,
openaiNextJs,
diff --git a/tooling/examples/src/generateExamples.ts b/tooling/examples/src/generateExamples.ts
index c26d353b..d8b26c6e 100644
--- a/tooling/examples/src/generateExamples.ts
+++ b/tooling/examples/src/generateExamples.ts
@@ -12,7 +12,7 @@ const commonParams: CommonParams = {
examplesFolder: path.join(repoRoot, "examples"),
nextjsVersion: "14.2.3",
viteVersion: "5.2.3",
- llmUiVersion: "0.4.0",
+ llmUiVersion: "0.6.0",
};
(async () => {