- Settings: your app’s settings screen lets the owner choose which widgets to show, where and how big.
- Rendering: a profile page fetches the widgets a visitor may see and draws them. @cskn/ui has the renderers.
Settings screen
If you use @cskn/ui, drop in<WidgetSettings />. Otherwise useWidgetSettings gives you the same behavior to render in your own design:
WidgetDefinition[]
What your app offers, translated to
locale when the catalog has a translation.Record<string, WidgetConfig>
The owner’s unsaved choices, keyed by widget id. Widgets added since they last saved appear switched off.
'not-activated' | 'private' | 'followers-only' | null
Set when at least one widget is on but something else hides it from visitors. Supply your own wording for each.
(id, value) => void
Edit the draft.
setOption(id, key, value) sets a widget-specific option.…
Save the draft.
saveError is 'not-activated' when the app is not on the owner’s profile, otherwise 'failed'.Sizes and slots
The
action slot holds buttons, not cards: only an action-layout widget may sit there, and it may sit nowhere else. slotsForLayout(layout) returns the slots to offer for a widget. A theme without a given region falls back to content, so an enabled widget is never lost.
Rendering a profile’s widgets
groupWidgetsBySlot always returns every slot key, possibly empty, and sends unknown slots to content.
Content layouts
EachWidgetInstance.content has a layout: list, grid, media, gallery, stat, text, progress, action, or custom. The custom layout carries a node tree built from a closed vocabulary (flex and grid containers; text, image, avatar, video, icon, button, badge, progress, divider, spacer leaves). There is no HTML, no style strings and no script, so the same tree is safe to render on someone else’s profile on any surface.