Serving data

Manifest & icons

The metadata the hub stores for each widget, and how icons work.

Every widget has a manifest — the metadata the hub stores alongside its HTML. You don’t write it directly; the hub builds it when you publish. But knowing the fields helps when you list widgets or debug versioning.

Manifest fields

FieldTypeMeaning
idstringStable widget id (returned by publish_widget).
namestringHuman-readable name (switcher + Mac list).
refreshMsintNative poll interval for this widget’s feed.
htmlHashstringSHA-256 (hex) of the HTML, for integrity.
versionintBumped on every update so the phone knows to refetch.
publishedAtdouble?First-published time (Unix seconds). Optional.
iconWidgetIcon?Switcher / Mac list / Lock Screen icon. Optional.
builtInSlugstring?If installed from a shipped template, its stable slug (e.g. "soundbar"). nil for custom widgets.
builtInVersionint?The template version it was installed from (drives “update available”).

list_widgets returns an array of these plus the activeWidgetId.

Icons

A WidgetIcon has a kind and a value:

{ "kind": "sfSymbol", "value": "thermometer" }
{ "kind": "emoji",    "value": "🎵" }
{ "kind": "png",      "value": "<base64-encoded PNG bytes>" }
KindvalueNotes
sfSymbolSF Symbol nameBest default — crisp, tint-safe, desaturates cleanly on the Lock Screen.
emojione emojiColorful in-app; flattens to a tinted silhouette on the Lock Screen.
pngbase64 PNG on input~256px, transparent background, monochrome silhouette, ≤256 KiB.

For a png, the hub stores the bytes, computes their SHA-256, and rewrites value to that hash (a cache key); the raw bytes are served at GET /widget/:id/icon. So a manifest you read back will show the hash, not the base64 you sent.

Set or change an icon without touching the HTML via set_widget_icon:

{ "id": "wgt_abc123", "icon": { "kind": "sfSymbol", "value": "thermometer.sun" } }