Building a new A2UI renderer means writing the bridge between the A2UI protocol stream and your target UI framework or platform. This guide walks you through the decision of whether to build at all, how to lean onDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/a2ui-project/a2ui/llms.txt
Use this file to discover all available pages before exploring further.
@a2ui/web_core for any web-based renderer, and what the full protocol compliance checklist looks like for v0.9.1, v1.0, and v0.8.
Should you build a new renderer?
Before starting, check whether an existing renderer already fits your target:React Renderer
@a2ui/react — v0.9 native with the Generic Binder, or legacy v0.8 via A2UIProvider.Angular Renderer
@a2ui/angular — Signal-based reactivity, DynamicComponent base class, extensible catalogs.Lit Renderer
@a2ui/lit — reference implementation, ships a basicCatalog, ideal for web components.Non-web Targets
Flutter, iOS, Android, or desktop — implement the protocol directly using the compliance checklist below.
@a2ui/web_core.
Web renderers: use @a2ui/web_core
If your target is any web framework — Vue, Svelte, Solid, Qwik, or a custom stack — do not reimplement message processing, state management, or schema validation from scratch. The @a2ui/web_core package is the framework-agnostic engine that all three maintained web renderers share, and it ships ~3,000 lines of battle-tested protocol logic.
What web_core provides
Every module you would otherwise have to write yourself is already in @a2ui/web_core:
| Module | What it does |
|---|---|
MessageProcessor | Processes the A2UI JSONL stream, dispatches messages, manages surface lifecycle |
SurfaceModel / SurfaceGroupModel | State management for surfaces, components, and data models |
DataModel / DataContext | Data-binding resolution, path-based lookups, template list rendering |
ComponentModel | Component tree state, adjacency list → tree resolution |
| Types & Schemas | TypeScript types for all A2UI components, primitives, colors, styles, and JSON schema validation |
| Expression parser | Client-side function evaluation (v0.9+) |
Version-specific exports
@a2ui/web_core publishes a separate API surface for each protocol version so you can target exactly the version your renderer needs:
The package root (
import ... from '@a2ui/web_core') defaults to the v0.8 entrypoint for backward compatibility. For new renderers, always import from the explicit versioned path such as @a2ui/web_core/v0_9. A dedicated @a2ui/web_core/v1_0 entrypoint is not yet published; v1.0 protocol support is currently implemented inside @a2ui/web_core/v0_9.The three things every web renderer must do
All three maintained renderers follow the same pattern —web_core owns the protocol, the renderer owns the UI:
Map A2UI component types to your framework's components
Create a catalog that maps each A2UI component name (
Text, Button, Column, etc.) to a framework component. Lazy-load implementations where possible to keep the initial bundle small.Subscribe to state changes from web_core and re-render
Instantiate a
MessageProcessor, feed it the agent’s JSONL stream, and subscribe to surface lifecycle events so your UI updates reactively whenever new messages arrive.Forward user actions back through the MessageProcessor
When a user interacts with a component (button click, form input, slider move), dispatch the resolved action back through the processor. The Generic Binder in v0.9 handles this automatically for components using
CommonSchemas.Action; in v0.8 you resolve context paths manually.Non-web renderers (mobile and desktop)
For platforms that cannot use@a2ui/web_core — Flutter, iOS (SwiftUI / UIKit), Android (Jetpack Compose), or desktop frameworks — you must implement the protocol directly. Use the compliance checklist in the next section as your specification.
The core architecture is identical even without web_core:
- A JSONL stream parser that decodes one JSON object per line
- A message dispatcher that routes each message type to the correct handler
- A surface registry keyed by
surfaceId - A component buffer (flat map) per surface, with tree resolution logic
- A data model store per surface, with path-based upsert semantics
- A data-binding resolver that resolves
{ path: "..." }references against the store - An action dispatcher that sends resolved user actions back to the agent
Protocol compliance checklist
Use the tab for the version you are targeting. v0.9.1 is the recommended starting point for all new renderers.- v0.9.1 — Current Production
- v1.0 — Release Candidate
- v0.8 — Legacy
I. Core protocol
- JSONL stream parsing — read a streaming response line by line; decode each line as a distinct JSON object.
- Message dispatcher — identify message types (
createSurface,updateComponents,updateDataModel,deleteSurface) and route to the correct handler. - MIME type validation — intercept payloads based on the
application/a2ui+jsonMIME type. - Surface management:
- Key surfaces by
surfaceId. createSurface: create the surface, bindcatalogId, registerthemeandsendDataModel.updateComponents: add/update components in flat format using"component": "Type"discriminators.deleteSurface: remove the surface and all associated data and components.
- Key surfaces by
- Component buffering — maintain a flat
Map<string, Component>per surface; reconstruct the UI tree by resolving ID references inchildrenarrays andchildfields. - Data model store — handle
updateDataModelusing standard JSON objects with upsert semantics. - Progressive rendering — render immediately upon parsing a valid root component (ID
root) insideupdateComponents. No special rendering-start signal is required. - Data-binding resolution — resolve simplified bound values: either literals or
{ "path": "..." }. - Dynamic lists — iterate over data arrays at
pathand render templates specified bycomponentId. - Client-side functions — evaluate registered catalog-defined functions (e.g.
formatStringinterpolation). - Client-to-server — dispatch
action(replaces v0.8userAction) with resolved context paths. Include the full client-side data model in metadata whensendDataModelwas requested. SendValidationFailederror messages when schema validation fails.
II. Basic component catalog
- Text —
variant(replaces v0.8usageHint) - Image —
fit,variant - Icon, Video, AudioPlayer, Divider
- Row / Column —
justify,align, childweight - List, Card
- Tabs —
tabs - Modal —
trigger,content - Button —
action,variant(primary,borderless) - CheckBox, TextField —
label,value,variant,checks - ChoicePicker — replaces v0.8
MultipleChoice;options,variant(mutuallyExclusive,multipleSelection) - Slider —
min,max(replaces v0.8minValue,maxValue)
Reference implementations
All three maintained web renderers are open-source and follow theweb_core pattern described above. Reading their source is the fastest way to understand how a compliant renderer is structured.
React renderer
v0.9 native with the Generic Binder. Includes
createComponentImplementation and createBinderlessComponentImplementation factories, plus visual parity tests against the Lit reference.Lit renderer
Reference implementation. Extend
A2uiLitElement and return an A2uiController to get automatic prop resolution and Shadow DOM encapsulation.Angular renderer
Signal-based. Configure via the
A2UI_RENDERER_CONFIG injection token and extend DynamicComponent for custom catalog entries.web_core source
The shared foundation. Browse
src/v0_9/ for MessageProcessor, SurfaceModel, DataModel, ComponentModel, and the expression parser.