From 8ef31f1dffac4795e80e1aecf6b91abff2981955 Mon Sep 17 00:00:00 2001 From: Md Mushfiqur Rahim <20mahin2020@gmail.com> Date: Sun, 24 May 2026 06:03:26 +0000 Subject: [PATCH 1/2] Add README for the Vue chat example --- examples/vue-chat/README.md | 94 +++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 examples/vue-chat/README.md diff --git a/examples/vue-chat/README.md b/examples/vue-chat/README.md new file mode 100644 index 000000000..631604a69 --- /dev/null +++ b/examples/vue-chat/README.md @@ -0,0 +1,94 @@ +# OpenUI Vue Chat + +A chat application built with [Nuxt 3](https://nuxt.com), [Vercel AI SDK](https://ai-sdk.dev), and [`@openuidev/vue-lang`](../../packages/vue-lang/) — demonstrating how to render structured LLM output as live Vue components. + +## How it works + +1. **User sends a message** via the chat input +2. **Server streams a response** using the Vercel AI SDK with OpenAI, guided by a system prompt written in openui-lang syntax +3. **`@openuidev/vue-lang` Renderer** parses the streaming openui-lang text and renders it as Vue components in real time +4. **Tool calls** (weather, stocks, math, web search) are displayed inline with status indicators + +## Setup + +### Prerequisites + +- Node.js 18+ +- [pnpm](https://pnpm.io/) +- An OpenAI API key + +### Install dependencies + +From the monorepo root: + +```bash +pnpm install +``` + +### Configure environment + +```bash +cp .env.example .env +``` + +Edit `.env` and add your OpenAI API key: + +``` +OPENAI_API_KEY=sk-... +``` + +### Generate the system prompt (optional) + +```bash +pnpm --filter vue-chat generate:prompt +``` + +The generated prompt lives at `generated/system-prompt.txt` and is checked in, so this step is only needed after modifying component definitions in `lib/library.ts`. + +### Run + +```bash +pnpm --filter vue-chat dev +``` + +Open [http://localhost:3000](http://localhost:3000). + +## Project structure + +``` +app.vue # Root component (renders NuxtPage) +nuxt.config.ts # Nuxt config (ssr: false, Tailwind CSS, Nitro bundling) +pages/ +└── index.vue # Chat UI with AI SDK Chat class + OpenUI Renderer +components/ +├── ChatHeader.vue # Top bar with title +├── ChatInput.vue # Message input + send/stop buttons +├── UserMessage.vue # Renders user message parts +├── AssistantMessage.vue # Renders assistant message with OpenUI Renderer +├── LoadingIndicator.vue # Animated loading dots +├── WelcomeScreen.vue # Start page with example prompts +└── openui/ # Vue component renderers for openui-lang output + ├── Stack.vue + ├── Card.vue + ├── TextContent.vue + ├── Button.vue + └── Chart.vue +lib/ +├── library.ts # OpenUI component definitions (Stack, Card, TextContent, Button, Chart) +└── tools.ts # AI tool definitions (weather, stocks, math, search) +server/ +└── api/chat.post.ts # AI SDK streaming endpoint +generated/ +└── system-prompt.txt # LLM system prompt describing the openui-lang syntax +assets/ +└── app.css # Tailwind CSS entry point +``` + +## Adding components + +1. Create a Vue component in `components/openui/` +2. Define it with `defineComponent()` in `lib/library.ts` +3. Run `pnpm --filter vue-chat generate:prompt` to update `generated/system-prompt.txt` +4. Commit the updated prompt file + +See the [`@openuidev/vue-lang` README](../../packages/vue-lang/README.md) for the full API. From d9d940f6aa852e0845ec70f18f61fbd45f62941a Mon Sep 17 00:00:00 2001 From: Md Mushfiqur Rahim <20mahin2020@gmail.com> Date: Sun, 24 May 2026 06:04:01 +0000 Subject: [PATCH 2/2] docs: fix Accordion typo in navigation and route naming - Rename directory accordian/ to accordion/ - Fix function name BlocksAccordianPage -> BlocksAccordionPage - Fix navigation ids, labels, and hrefs in both component and design-system configs - Add permanent redirect from old path to maintain backward compatibility Closes #553 --- .../blocks/{accordian => accordion}/page.module.css | 0 .../components/blocks/{accordian => accordion}/page.tsx | 2 +- docs/app/components/config/navigation.ts | 7 +++---- docs/next.config.mjs | 5 +++++ docs/shared/design-system/config/navigation.ts | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) rename docs/app/components/blocks/{accordian => accordion}/page.module.css (100%) rename docs/app/components/blocks/{accordian => accordion}/page.tsx (99%) diff --git a/docs/app/components/blocks/accordian/page.module.css b/docs/app/components/blocks/accordion/page.module.css similarity index 100% rename from docs/app/components/blocks/accordian/page.module.css rename to docs/app/components/blocks/accordion/page.module.css diff --git a/docs/app/components/blocks/accordian/page.tsx b/docs/app/components/blocks/accordion/page.tsx similarity index 99% rename from docs/app/components/blocks/accordian/page.tsx rename to docs/app/components/blocks/accordion/page.tsx index d08eb0735..262644945 100644 --- a/docs/app/components/blocks/accordian/page.tsx +++ b/docs/app/components/blocks/accordion/page.tsx @@ -172,7 +172,7 @@ function AccordionControls({ ); } -export default function BlocksAccordianPage() { +export default function BlocksAccordionPage() { const [variant, setVariant] = useState("clear"); const [type, setType] = useState("single"); diff --git a/docs/app/components/config/navigation.ts b/docs/app/components/config/navigation.ts index 5fd9dcc81..d80c4bd75 100644 --- a/docs/app/components/config/navigation.ts +++ b/docs/app/components/config/navigation.ts @@ -39,10 +39,9 @@ export const BLOCKS_NAV_ITEMS: NavGroup[] = [ label: "Individual blocks", items: [ { - id: "accordian", - label: "Accordian", - href: "/components/blocks/accordian", - badgeText: "Fixing", + id: "accordion", + label: "Accordion", + href: "/components/blocks/accordion", }, { id: "button-group", label: "Buttons", href: "/components/blocks/button-group" }, { id: "callout", label: "Callout", href: "/components/blocks/callout" }, diff --git a/docs/next.config.mjs b/docs/next.config.mjs index f1618f9b6..a5ee4b0e9 100644 --- a/docs/next.config.mjs +++ b/docs/next.config.mjs @@ -46,6 +46,11 @@ const config = { destination: "/blog/beyond-the-chatbar", permanent: true, }, + { + source: "/components/blocks/accordian", + destination: "/components/blocks/accordion", + permanent: true, + }, ]; }, async rewrites() { diff --git a/docs/shared/design-system/config/navigation.ts b/docs/shared/design-system/config/navigation.ts index 22572aea1..565566e25 100644 --- a/docs/shared/design-system/config/navigation.ts +++ b/docs/shared/design-system/config/navigation.ts @@ -41,7 +41,7 @@ export const BLOCKS_NAV_ITEMS: NavGroup[] = [ id: "individual-blocks", label: "Individual blocks", items: [ - { id: "accordian", label: "Accordian", href: `${BASE}/blocks/accordian` }, + { id: "accordion", label: "Accordion", href: `${BASE}/blocks/accordion` }, { id: "button-group", label: "Buttons", href: `${BASE}/blocks/button-group` }, { id: "callout", label: "Callout", href: `${BASE}/blocks/callout` }, { id: "image-items", label: "Image items", href: `${BASE}/blocks/image-items` },