Returning a widget
A widget is just another glance block. The SDK’swidgetResult helper wraps one
for you:
{ "type": "widget", "html", "height?", "data?", "label?" }.
It counts against the normal 3-block budget, and can’t sit inside a row.
The sandbox
Your document renders in an iframe withsandbox="allow-scripts" and
deliberately without allow-same-origin:
The bridge
Host → widget, once, after load:data is your block’s data verbatim. Style for both modes and switch on
theme.mode — never on prefers-color-scheme, which follows the OS while
the notch stays dark.
Widget → host:
Full wire details: Widget bridge reference.
A complete minimal widget
- Theme comes from the bridge, not the OS.
- A
ResizeObserverreports real height. - A guard refuses to report a collapsed measurement — a hidden frame measuring 0 would otherwise pin your card at the 60px floor.
The corner
Every card VoiceOS shows is cut at the same corner radius, and the surface does the cutting, not your document. Your card arrives as a rectangle; the host rounds it. That matters the moment you paint anything to the card’s own edge — a background, a border, a header wash, a full-bleed image. Draw that at a radius of your own and there are two corners: yours, and the host’s arc slicing across it a few pixels out. So use the variable, never a number:--k-radius is set before your CSS runs and is 26px — the same corner the
notch cuts confirmation cards at. It’s still not a constant you can inline: the
same html renders into more than one surface, and a surface whose clip is
concentric with a different shell uses its own value (VoiceOS’s pill clips at
25). The host sends its real value on voiceos:init, so var(--k-radius) is
correct everywhere and a literal is correct in exactly one place.
Only the OUTER corner is host-owned. Rows, chips, thumbnails, inputs, and
avatars are yours — match the product you’re fronting. If you build with the
Widget Kit, its card shells already carry
border-radius: var(--k-radius).Height, done right
Declare an honestheight and report corrections. A good estimate alone
drifts as content varies; a correction alone means a visible jump on every card.
Measure your real card once, hardcode the estimate, keep the observer.
Don’t hand-roll it
Everything on this page — bridge, theming, resize guards, caps, degradation — is implemented once in the Widget Kit, the same design system the Integration Studio uses for every card it generates.The Widget Kit
Composable card components, brand accents with automatic contrast repair, and
a bridge runtime you never have to write.

