Skip to content

Add @openuidev/vue-lang — Vue 3 runtime adapter#402

Open
dc-riskhub wants to merge 2 commits intothesysdev:mainfrom
dc-riskhub:dc-riskhub/add-vue-support
Open

Add @openuidev/vue-lang — Vue 3 runtime adapter#402
dc-riskhub wants to merge 2 commits intothesysdev:mainfrom
dc-riskhub:dc-riskhub/add-vue-support

Conversation

@dc-riskhub
Copy link

@dc-riskhub dc-riskhub commented Mar 26, 2026

Summary

  • Adds @openuidev/vue-lang package — Vue 3.5+ runtime adapter for OpenUI, following the identical pattern established by svelte-lang
  • Adds vue-chat example — full Nuxt 3 chat app with Vercel AI SDK, mirroring svelte-chat
  • Addresses #318 (comment): "Vue renderer would be next"

@openuidev/vue-lang — Runtime Adapter

File Purpose
library.ts Narrows ComponentRenderProps to VNode, wraps coreDefineComponent/coreCreateLibrary
Renderer.vue Parses OpenUI Lang, manages form state, renders component tree via h()
RenderNode.vue Dynamic <component :is> with onErrorCaptured error boundary
context.ts provide/inject with typed InjectionKey symbols, 8 composables
validation.ts Form validation via reactive() (mirrors svelte-lang's $state)
index.ts Full public API mirroring svelte-lang's export structure

vue-chat — Example App

Full Nuxt 3 chat application using the Vercel AI SDK (@ai-sdk/vue Chat class + streamText):

  • 5 OpenUI components: TextContent, Button, Card, Stack, Chart (Chart.js)
  • API route (/api/chat): streamText with tool support (weather, stocks, calculator, web search)
  • Streaming UI: real-time message rendering with tool call indicators (spinner → checkmark)
  • Welcome screen with conversation starters
  • System prompt generated via scripts/generate-prompt.mjs

Architecture

Same pipeline as svelte-chat:

  1. User sends message → Chat.sendMessage() (Vercel AI SDK)
  2. Server streams response via streamText().toUIMessageStreamResponse()
  3. Client parses message parts → AssistantMessage extracts text content
  4. Renderer from vue-lang parses OpenUI Lang → renders Vue component tree
  5. Button clicks → triggerActionBuiltinActionType.ContinueConversation

Pipeline parity with react-lang and svelte-lang

  • Same createParser(library.toJSONSchema()) from lang-core
  • Same component resolution: library.components[typeName] → pass props + renderNode
  • Same form state management: getFieldValue/setFieldValue/triggerAction
  • Same callback signatures: onAction, onStateUpdate, onParseResult
  • Error boundary preserves last valid render (matches React behavior)

Test plan

vue-lang

  • 30 tests passing (library: 8, renderer: 7, validation: 15)
  • pnpm --filter @openuidev/vue-lang build — Vite library mode (6.27 kB)
  • pnpm --filter @openuidev/vue-lang test — Vitest with jsdom

vue-chat

  • Welcome screen renders with 4 conversation starters
  • API route responds with Vercel AI SDK streaming protocol
  • Tool definitions loaded (get_weather, get_stock_price, calculate, search_web)
  • pnpm install clean in monorepo context
  • End-to-end with OpenAI API key (requires OPENAI_API_KEY in .env)

Follows the same pattern as svelte-lang: thin adapter over lang-core
with Vue-specific type narrowing, provide/inject context, and a
recursive Renderer component.

- Vue 3.5+ with Composition API and <script setup>
- ComponentRenderProps narrowed to VNode
- Renderer.vue: parses OpenUI Lang, manages form state, renders tree
- RenderNode.vue: dynamic <component :is> with onErrorCaptured boundary
- Context via provide/inject with typed InjectionKey symbols
- 8 composables: useOpenUI, useTriggerAction, useIsStreaming, etc.
- Form validation via reactive() (mirrors svelte-lang's $state)
- 30 tests (library, renderer, validation) — all passing
- Vite library mode build (6.27 kB)
@dc-riskhub dc-riskhub mentioned this pull request Mar 26, 2026
Full chat example mirroring svelte-chat with Vue 3.5 + Composition API:

- Nuxt 3 app with Nitro server (SSR disabled, client-only SPA)
- Vercel AI SDK v6: Chat class from @ai-sdk/vue, streamText on server
- 5 OpenUI components: TextContent, Button, Card, Stack, Chart (Chart.js)
- Library definition with Zod schemas, same structure as svelte-chat
- API route: /api/chat with tool support (weather, stocks, calc, search)
- System prompt generated via scripts/generate-prompt.mjs (uses jiti)
- Welcome screen with conversation starters
- Streaming message display with tool call indicators
- Auto-scroll on new messages

Setup: copy .env.example to .env, add OPENAI_API_KEY, start with nuxt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant