A2UI Progressive Rendering — Live Demo

Interactive illustration of three proposed A2UI v1.0 primitives: pending state, streaming lifecycle flag, and append patch op. Every change in the rendered UI (left) corresponds to a wire message shown on the right — exactly as it would flow over a real A2UI WebSocket.

Fully client-side simulation. No backend. Source: index.html. RFC: RFC.md.

Proposal 1 — Pending state

A component with path-bound fields that resolve to undefined should render a shimmer placeholder by default. Today this is per-client convention; the proposal standardizes it.

Rendered UI

Wire messages

Without the proposal, different clients would render this skeleton differently (blank / spinner / shimmer / error). Same JSON, inconsistent UX. With the proposal, the pending behavior is spec-guaranteed.

Proposal 2 — Streaming lifecycle flag

updateDataModel messages carry an optional streaming flag. While true, the renderer shows a live indicator (typewriter caret). On false (or omitted), the value is final.

Rendered UI

Wire messages

The caret is a protocol signal, not just a style. Action buttons with path-bound event names can stay disabled while streaming: true and enable on streaming: false — no per-client guard code.

Proposal 3 — append patch op

Today every updateDataModel replaces the value at a path (set). Streaming a 2,000-char response takes ~100 KB of wire traffic because each delta re-sends the accumulated value. The append op sends only the delta — ~40× less bandwidth for long text.

Side-by-side: set vs. append

set (current v0.9)

bytes on wire0
messages sent0

append (proposed)

bytes on wire0
messages sent0
Savings grow with text length. A ~100-char headline shows 16× reduction. A 10,000-char article shows ~48×. Negligible for small values — the proposal keeps set as the default so small fields pay nothing.