Quickstart

Build a streaming Nuxt chat with Vue, assistant-ui, and the AI SDK.

This guide adds a streaming chat to a Nuxt app in about five minutes. The runtime stays in a client-only component and the model call stays in a Nitro route.

Install the runtime

Install the Vue binding, the AI SDK runtime, and an AI SDK provider:

pnpm add @assistant-ui/vue @assistant-ui/ai-sdk ai @ai-sdk/openai react

react is the AI SDK runtime's substrate — an optional peer of @assistant-ui/ai-sdk, so it does not install on its own. For nuxi typecheck, add @types/react as a dev dependency: a type-only react reference rides through the core runtime types.

pnpm add -D @types/react

Add your provider key to .env:

.env
OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Install the styled components

Add the Vue assistant-ui registry once in components.json:

components.json
{
  "registries": {
    "@assistant-ui": "https://r.assistant-ui.com/vue/{name}.json"
  }
}

Install the chat surface:

npx shadcn@latest add @assistant-ui/thread @assistant-ui/thread-list

This writes Vue components under components/assistant-ui. The registry installs their assistant-ui, Vue, and UI dependencies.

Create the assistant client

Use a .client.vue file so the runtime is created only in the browser:

app/components/Assistant.client.vue
<script setup lang="ts">
import { AuiConfig, AuiProvider } from "@assistant-ui/vue";
import { AISDKChat } from "@assistant-ui/ai-sdk";
import Thread from "~/components/assistant-ui/thread.vue";

const config = AuiConfig({
  threads: AISDKChat(),
});
</script>

<template>
  <AuiProvider :config="config">
    <Thread class="h-dvh" />
  </AuiProvider>
</template>

AISDKChat() creates one streaming thread. Its default transport sends requests to /api/chat.

Add the streaming route

Create the Nitro route that receives UI messages and returns an AI SDK UI message stream:

server/api/chat.post.ts
import { openai } from "@ai-sdk/openai";
import { convertToModelMessages, streamText, type UIMessage } from "ai";

export default defineEventHandler(async (event) => {
  const { messages, system } = await readBody<{
    messages: UIMessage[];
    system?: string;
  }>(event);

  const result = streamText({
    model: openai("gpt-5.6-luna"),
    messages: await convertToModelMessages(messages),
    system,
  });

  return result.toUIMessageStreamResponse();
});

Render the assistant

Nuxt recognizes the .client.vue suffix and only mounts this component in the browser:

app/pages/index.vue
<template>
  <Assistant />
</template>

Start the app with pnpm dev, then send a message. The response streams from server/api/chat.post.ts into the thread.

Next steps

Use AISDKThreads when the chat needs a thread list, server rendering to understand the .client.vue boundary, and Tool UI to render tool calls.