Components & Structure
Why Flat Lists?
Traditional nested approach:
- LLM must generate perfect nesting in one pass.
- Hard to update deeply nested components.
- Difficult to stream incrementally.
A2UI adjacency list:
- ✅ Flat structure, easy for LLMs to generate.
- ✅ Send components incrementally.
- ✅ Update any component by ID.
- ✅ Clear separation of structure and data.
The Adjacency List Model
{
"surfaceUpdate": {
"components": [
{"id": "root", "component": {"Column": {"children": {"explicitList": ["greeting", "buttons"]}}}},
{"id": "greeting", "component": {"Text": {"text": {"literalString": "Hello"}}}},
{"id": "buttons", "component": {"Row": {"children": {"explicitList": ["cancel", "ok"]}}}},
{"id": "cancel", "component": {"Button": { ... }}},
{"id": "ok", "component": {"Button": { ... }}}
]
}
}
Components reference children by ID, not by nesting.
Component Basics
Every component has:
- ID: Unique identifier (e.g.,
"welcome-message"). - Type: Component type (
Text,Button,Card). - Properties: Configuration specific to that type.
Static vs. Dynamic Children
Static (explicitList)
Fixed list of child IDs.
{"children": {"explicitList": ["back-btn", "title", "menu-btn"]}}
Dynamic (template)
Generate children from a data array.
{"children": {"template": {"dataBinding": "/items", "componentId": "item-template"}}}
For each item in /items, render the item-template.
Hydrating with Values
- Literal: Fixed value.
{"text": {"literalString": "Welcome"}} - Data-bound: From data model.
{"text": {"path": "/user/name"}}
Incremental Updates
- Add: Send new
surfaceUpdatewith new component IDs. - Update: Send
surfaceUpdatewith existing ID and new properties. - Remove: Update parent’s children list to exclude removed IDs.
Custom Components
Beyond the standard catalog, clients can define custom components (Charts, Maps, etc.). See the Custom Components Guide.