segfault labs

Surfaces

A surface is a place your module renders. Each surface in the manifest pairs with a register* call in your code (matched by id, or by kind for windows). Each surface renders in its own iframe.

KindWhere it appearsManifest extras
widgetFloating, draggable; snaps to 8 screen zones, reorders within a stack, pins.gated:false keeps it visible while the overlay panel is closed.
windowA draggable window with a dock launcher button.label, icon, order drive the dock button. Your registerWindow({ kind }) must use the surface id as its kind.
settingsA section in the Settings window.label, icon, order place it in the sidebar.

Widgets

ps.registerWidget({
  id: 'badge',     // matches the manifest surface id
  gated: false,    // visible even when the overlay panel is closed
  render(root) { /* draw into root */ },
})

Windows

A window gets a draggable frame and a dock button. The registerWindow kind must equal the manifest surface id.

ps.registerWindow({
  kind: 'main',                                  // = the manifest surface id
  title: 'My Module',
  initial: { w: 360, h: 280 },
  launcher: { icon: 'gauge', label: 'My Module', order: 200 },
  render(root) { /* draw into root */ },
})

Settings

ps.registerSettings({
  id: 'prefs',
  title: 'My Module',
  icon: 'gauge',
  order: 220,
  render(root) { /* draw your settings UI */ },
})

Sharing state across surfaces

Because each surface is a separate iframe, state that several surfaces share (e.g. a setting a widget reads) must go through ps.host.storage. After a settings surface writes a value, call ps.reload() so the other surfaces re-render with it.