---
url: /guide/7guis.md
---
# 7 GUIs
To verify that Vue Lynx behaves identically to Vue in real GUI scenarios, we forked the [7 GUIs](https://eugenkiss.github.io/7guis/) examples from the [official Vue.js documentation](https://vuejs.org/examples/#7-guis-counter) — seven classic tasks that cover typical challenges in GUI programming, from a simple counter to a full spreadsheet.
## Examples
### 1. Counter
A simple button that increments a counter. Tests basic state management and event handling.
### 2. Temperature Converter
Bidirectional conversion between Celsius and Fahrenheit. Tests two-way data flow and constraint handling.
### 3. Flight Booker
A flight booking form with conditional validation. Tests constraints, conditional visibility, and input validation.
### 4. Timer
An elapsed-time gauge with adjustable duration. Tests concurrency, competing user/signal interactions, and continuous updates.
### 5. CRUD
A filterable list with create, read, update, and delete operations. Tests managing a dynamic collection of data.
### 6. Circle Drawer
Draw circles on a canvas with undo/redo support. Tests custom drawing, a non-trivial undo model, and dialog control flow.
### 7. Cells
A simple spreadsheet with formula evaluation. Tests change propagation, cell references, and reactive computation.
---
url: /guide/ai-chat.md
---
# AI Chat
A full-featured AI chatbot ported feature-by-feature from the official [Nuxt AI Chatbot template](https://github.com/nuxt-ui-templates/chat) (Nuxt UI + Vercel AI SDK) — probably the most demanding "real-world" validation of Vue Lynx so far: streaming responses with thinking/reasoning, markdown with highlighted code blocks and tables, tool-call cards (weather, charts, web-search sources), chat history with date grouping, votes, message editing, share/rename/delete flows, a model picker, persisted runtime theming with light/dark mode, attachments, fuzzy command-palette search, and a responsive mobile layout with a slide-over sidebar.
Try the quick prompts below — *"What is the weather in Bordeaux?"* streams a reasoning section and a weather card; *"Show me a chart of sales data"* renders an SVG line chart; *"Help me create a Vue composable"* shows markdown with highlighted code. Scan the QR code in the native tab to run the same bundle in [LynxExplorer](https://lynxjs.org/guide/start/quick-start.html).
The playground above runs fully self-contained: the app probes for its API server and, when unreachable, falls back to an in-app demo backend with the same seeded history and deterministic mock AI streams. When you run the example locally with `pnpm dev:server`, the same UI talks to a standalone Node server that reimplements the Nuxt template's API routes — and streams **real models** through the [Vercel AI Gateway](https://vercel.com/docs/ai-gateway) if you set `AI_GATEWAY_API_KEY`.
## Native chat techniques
A polished chat send is not one animation. It is a handoff between the composer, message list, keyboard, and streaming response. [Vercel’s account of building the v0 iOS app](https://vercel.com/blog/how-we-built-the-v0-ios-app) inspired us to describe the work through those visible moments, then trace each moment back to the system that makes it possible.
### The first send establishes the stage
Before an assistant message exists, the app captures the composer and viewport geometry. The outgoing text stays in a temporary animation layer while the app commits the real message, scroll position, and response space. The assistant reveal begins only after that update, so there is no target-position flash.
The launch distance depends on the bubble height, viewport, composer, and keyboard. We stage the bubble at the captured composer position, commit layout, then start its transform on a later frame. Layout and animation never compete for the same first frame.
### The second send is the real test
Repeat sends expose mistakes that the empty state hides. Native aligns the new user turn at the top, but keeps the previous turn stable until the moving bubble reaches its target. Vue Lynx [`nextTick()`](https://vue.lynxjs.org/guide/api/vue-lynx/Function.nextTick) waits for pending operations to reach the main thread before [`scrollIntoView`](https://lynxjs.org/api/elements/built-in/scroll-view#scrollintoview) performs the final alignment. Only then does the assistant stream appear.
Web uses a different policy because it does not have the same native positioning guarantees: observed `scroll-top` updates keep the message list pinned to the bottom during sends and streaming. The interaction stays familiar even when the mechanism changes.
### The keyboard participates in layout
Lynx [`` elements do not avoid the keyboard automatically](https://lynxjs.org/api/elements/built-in/input#keyboard-avoidance). The composer remains absolutely positioned at the bottom and listens for the [`keyboardstatuschanged` global event](https://lynxjs.org/api/lynx-api/event/global-event#keyboardstatuschanged). It applies the reported keyboard height with `setNativeProps`; the message list follows only if it was already following new output.
### Gesture feedback stays on the main thread
Drawer gestures and press feedback use Vue Lynx [Main Thread Script](https://vue.lynxjs.org/guide/main-thread-script). Functions marked with `'main thread'` update element styles from `main-thread-bindtouch*` events without a background-thread round trip. The regular `tap` handler still performs the application action on Vue’s background thread.
## Porting notes
The port keeps the original's data model (AI SDK v5 `UIMessage` parts over the UI-message-stream protocol) and nearly all of its composable/page logic, while re-implementing the DOM-coupled layers with Lynx elements:
| Aspect | Nuxt original | Vue Lynx |
|--------|---------------|----------|
| **UI kit** | @nuxt/ui v4 (`UChat*`, `UDashboard*`, Reka UI portals) | Hand-built Lynx components (`view`/`text`/`image`/`scroll-view`/`input`) with Nuxt UI's semantic design tokens |
| **Chat state** | `@ai-sdk/vue` `useChat` | Custom `useChat` speaking the same protocol (SSE on web; incremental polling + cancellation on native) |
| **Markdown** | Comark + Shiki (HTML) | Markdown, including tables, → native-node renderer + lightweight code tokenizer |
| **Charts** | nuxt-charts / Unovis (SVG DOM) | Chart generated as an inline SVG string for the native `