# AI-first system tour The "anything can drive the UI" architecture — the contract every interactive element opts into, the command bus that dispatches actions, the DSL that makes scripts and LLM output ergonomic, and the LLM integration that wires the whole thing into a chat surface. It's one system, designed end-to-end. Reading top-to-bottom is the fastest way to understand it. ## Overview ``` ┌─ producers ─────────────────────┐ ┌─ executor ──────────────────┐ │ ⌨ console (window.commandBus) │ │ command-bus.ts │ │ 📜 scripts (.script DSL) │ ─▶ │ • dispatch(cmd) │ │ 🤖 LLM (```action blocks) │ │ • handlers map │ │ 🔌 WebSocket (optional) │ │ • vars + history │ └─────────────────────────────────┘ │ • listActions / readState │ └─────────┬───────────────────┘ │ ┌───────────────────┴───────────────────┐ │ │ ▼ ▼ ┌──────────────┐ ┌──────────────────┐ │ DOM actions │ │ replay layer │ │ (click/fill/ │ │ • virtual cursor │ │ navigate/…) │ │ • ripple on click│ └──────────────┘ └──────────────────┘ ``` Every interactive element opts in by adding `data-action=""`. That's the entire contract. From there, the bus can find it, scripts can target it, and the LLM can drive it. ## The `[data-action]` convention Every interactive UI element gets a stable id: ```tsx Resources ``` **Naming:** lowercase, kebab-case, prefixed by the surface it lives in: | Prefix | Surface | |---|---| | `nav-*` | Sidebar nav links (`nav-overview`, `nav-resources`, …) | | `nav-mobile-*` | Mobile sheet versions of nav | | `appbar-*` | Top bar controls (`appbar-search`, `appbar-notifications`) | | `avatar-*` | Avatar dropdown items | | `-*` | Route-specific (`assistant-clear`, `settings-save`) | | `home-tile-*`, `run-script-*`, etc. | Domain-grouped | **Why this works:** the bus introspects the DOM at dispatch time — `commandBus.listActions()` returns every visible `[data-action]` in the page right now. New components are automatically scriptable as long as they tag their interactive slots. No central registry to maintain. **One gotcha:** elements rendered in portals (closed dropdowns, sheets, dialogs) appear in the DOM but aren't visible. The `listActions()` filter uses `Element.checkVisibility()` + `offsetParent` + bbox checks to exclude those — so the LLM doesn't see actions it can't actually click. ## The command bus `app/lib/command-bus.ts`. Single dispatch point. Built-in handlers: | Command | Args | Purpose | |---|---|---| | `navigate` | `path` | React Router navigation | | `click` | `target` | Find `[data-action=target]`, scroll into view, click | | `fill` | `target`, `value` | Set input value, fire input + change events | | `submit` | `target` | Submit the form containing target | | `select` | `target`, `value` | Set `