Skip to main content
Surfaces let your extension add UI content to predefined locations in the Aether interface without replacing built-in components. Each surface registration targets a named slot and contributes a declarative UI tree that Aether renders in that location alongside any other registered content.

API signature

registerSurface returns a cleanup function. Call it to remove the surface registration and trigger a re-render.

Available slots

Drawer slots and ordering

The drawer.header and drawer.footer slots remain fixed while the conversation list scrolls. The legacy drawer slot remains supported and renders at the tail of the conversation list in this order:
  1. drawer
  2. drawer.list.end
  3. Built-in extension page launchers

Drawer opened event

Listen to drawer.opened to trigger logic when the conversation drawer opens:
On mobile, drawer.opened fires once for each closed-to-open transition, including swipe gestures. On tablet, it fires once when the permanent drawer enters composition (stable-open recompositions do not re-trigger it).

SurfaceDefinition fields

string
Unique identifier for this surface registration. Aether uses this to track and de-duplicate registrations from the same extension. If omitted, Aether generates one from the slot and registration order.
number
Controls the rendering order when multiple extensions register the same slot. Lower values render first. Defaults to 0 when omitted.
function
A factory function that receives a render context and returns a ui node tree. The function may be synchronous or async. Use either render or tree.
object
A static ui node tree used when render is omitted.

Render context

Aether passes fields including the following to your render function on every render cycle:

Example

index.ts
Call aether.invalidate() to force a re-render of all surfaces when your extension’s internal state changes. Aether does not automatically re-render surfaces on arbitrary extension-side mutations — only on storage writes, action invocations, and explicit invalidation.
Use order to ensure your surface renders in the right position when multiple extensions contribute to the same slot. Registrations with the same order value are sorted by their scoped ID as a stable tiebreaker.