# Chat Layout Build AI chat interfaces with message streams, reasoning, tool calling, and Vercel AI SDK integration. ## When to use - AI chatbot interfaces - Customer support chat - Any conversational UI with streaming responses ## Setup ### Install dependencies **Nuxt:** ```bash pnpm add ai @ai-sdk/gateway @ai-sdk/vue @comark/nuxt ``` **Vue (Vite):** ```bash pnpm add ai @ai-sdk/gateway @ai-sdk/vue @comark/vue ``` ### Register Comark module **Nuxt:** ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: [ '@nuxt/ui', '@comark/nuxt' ] }) ``` **Vue (Vite):** No module registration needed, import directly from `@comark/vue`. > `@comark/nuxt` (or `@comark/vue` for Vue projects) provides the `Comark` component used to render AI responses as streaming Markdown, it incrementally renders tokens as they arrive and automatically enables Nuxt UI's prose components. ### Dark mode for syntax highlighting When using the `highlight` plugin, add the following CSS to your stylesheet: ```css [main.css] html.dark .shiki span { color: var(--shiki-dark) !important; background-color: var(--shiki-dark-bg) !important; font-style: var(--shiki-dark-font-style) !important; font-weight: var(--shiki-dark-font-weight) !important; text-decoration: var(--shiki-dark-text-decoration) !important; } ``` ### Server endpoint Using [Vercel AI Gateway](https://vercel.com/ai-gateway) (recommended): ```ts [server/api/chat.post.ts] import { streamText, convertToModelMessages, toUIMessageStream, createUIMessageStreamResponse } from 'ai' import { gateway } from '@ai-sdk/gateway' export default defineEventHandler(async (event) => { const { messages } = await readBody(event) const result = streamText({ model: gateway('anthropic/claude-sonnet-5'), instructions: 'You are a helpful assistant.', messages: await convertToModelMessages(messages) }) const stream = toUIMessageStream({ stream: result.stream }) return createUIMessageStreamResponse({ stream }) }) ``` Or with a direct provider (e.g., `pnpm add @ai-sdk/openai`): ```ts [server/api/chat.post.ts] import { streamText, convertToModelMessages, toUIMessageStream, createUIMessageStreamResponse } from 'ai' import { openai } from '@ai-sdk/openai' export default defineEventHandler(async (event) => { const { messages } = await readBody(event) const result = streamText({ model: openai('gpt-5-nano'), instructions: 'You are a helpful assistant.', messages: await convertToModelMessages(messages) }) const stream = toUIMessageStream({ stream: result.stream }) return createUIMessageStreamResponse({ stream }) }) ``` ## Component tree ``` UDashboardPanel ├── #header → UDashboardNavbar ├── #body → UContainer → UChatMessages │ ├── #content → UChatReasoning, UChatTool, Comark │ └── #indicator (loading) └── #footer → UContainer → UChatPrompt └── UChatPromptSubmit ``` ## Full page chat ```vue [pages/chat/[id].vue] ``` ## Key components - `UChatMessages` — scrollable message list with auto-scroll. Props: `messages`, `status`. Slots: `#content` (per message), `#actions`, `#indicator`. - `UChatMessage` — individual bubble. Props: `message`, `side` (`'left'`/`'right'`). - `UChatReasoning` — collapsible reasoning block. Auto-opens during streaming, auto-closes when done. Use `isPartStreaming(part)` from `@nuxt/ui/utils/ai`. - `UChatTool` — tool invocation status. Use `isToolStreaming(part)`. Variants: `'inline'` (default), `'card'`. - `UChatPrompt` — enhanced textarea for chat. Its typed API exposes a selected subset of `UTextarea` props, forwards additional attributes to the underlying textarea, and adds chat-specific props such as `error` and `submitOnEnter`. - `UChatPromptSubmit` — submit button with automatic status handling (send/stop/reload). - `UChatPalette` — layout wrapper for chat inside overlays. ## Chat in a modal ```vue ``` ## With model selector ```vue ``` ## Conversation sidebar Combine with dashboard layout for a ChatGPT-like interface: ```vue [layouts/dashboard.vue] ```