@hyperfrontend/features/hosteeHostee
Hostee-side SDK for feature apps — feature initialization, contract declaration, and lifecycle.
import { createFeature } from '@hyperfrontend/features/hostee'
const feature = createFeature({
name: 'clock',
contract: {
emitted: [{ type: 'tick' }],
accepted: [{ type: 'set-timezone' }],
},
})
await feature.ready()
feature.on('set-timezone', ({ tz }) => render(tz))
setInterval(() => feature.send('tick', Date.now()), 1000)
API
| Export | Purpose |
|---|---|
createFeature | Connect a feature app to its host; returns send/on/ready/close. |
FeatureHandle | Type of the handle returned by createFeature. |
ready() resolves once the wire handshake with the host completes, and rejects if the host does not open the connection within readyTimeoutMs (default 10 s; an error with reason: 'ready-timeout' is also emitted). Sends issued before the handshake completes queue and flush on open. send emits a contract action to the host; on subscribes to host messages and the open/closing/close/error/presentation/resize lifecycle events (closing is the flush window before a polite close completes). setDirty declares unsaved work to the host. close disconnects from the host politely.
Presentation
The host owns how the feature is surfaced; the SDK receives that decision and prepares the document, so the app author only has to make the layout responsive.
Right after open, the host announces the display mode along with the frame's initial dimensions — read the mode from feature.displayMode or the presentation event ({ mode }); the dimensions arrive as the first resize event, no extra round trip. In the iframe modes the host then reports every change to the frame's usable space as exact pixels; the SDK sizes html/body to match and re-emits each as resize ({ width, height }). In popup/standalone the browser window is the viewport and resize comes from the feature's own window. Responding to the reported width and height — media/container queries, reflow, breakpoints — is the app author's job.
In dialog mode the frame spans the host's viewport, transparent. The SDK places your root element (the body's first element child, or pass root to createFeature) at the agreed position — centered by default — and sizes it to the agreed inner-box dimensions; everything around it is the backdrop. You style the box itself — background, border, shadow — since an unstyled box is invisible against the transparent backdrop. The SDK detects pointer interaction on the bare backdrop and Escape presses and reports them to the host as dismiss signals — pure reports: the SDK tears nothing down itself, and if the host's policy is to close, the ordinary polite close (closing flush window included) follows. Because the pane covers the whole viewport, dragging or resizing the box is ordinary in-document CSS/pointer work if you want it — nothing crosses the boundary.
The body reset (resetBody, on by default) keeps html/body margin-free and transparent, with a color-scheme pin matched to the host frame — overriding the background or color-scheme with an opaque/dark scheme breaks the transparency that embedded blending and dialog backdrops depend on.
It applies on a standalone visit too, and its stylesheet is injected when createFeature runs — landing after the page's own stylesheet and winning at equal specificity. So paint the feature's background on its root layout element, never on body; a body { background: … } rule silently loses to the reset. Pass resetBody: false to opt out entirely and own the reset yourself.
API Reference
ƒ Functions
Creates a nexus broker for the feature, resolves the host window, and returns a handle for messaging and lifecycle. When
protocol selects the v1 or v2 envelope, the feature negotiates it with the host during the connection handshake and messages travel encrypted once it opens. A version announces the contract cut this feature holds (overriding any contract.version), so the handshake can deny hosts built against an incompatible cut.Parameters
| Name | Type | Description |
|---|---|---|
§options | FeatureOptions | Feature name, contract, and optional version, root-element, and security settings. |
Returns
FeatureHandlesend, on, ready, and close.Example
Initializing a clock feature
const feature = createFeature({ name: 'clock', contract, version: '1.2.0', protocol: 'v2', sharedKey: 'pre-shared-key' })
feature.ready().then(() => feature.send('timeUpdated', { time: Date.now() }))
feature.on('setTimezone', (data) => console.log(data))◈ Interfaces
Properties
readonly displayMode:DisplayModenull before the announcement arrives (it is the first message after open) and after the channel closes.Structurally compatible with nexus's channel contract action shape so the same contract can drive both messaging and the shell type generator.
Properties
required?:booleanaccepted entries. Unflagged actions never gate the connection, so additive contract evolution stays non-breaking.respondsWith?:stringThis is the same shape the on-disk
*.contract.json files and the shell generator consume.Properties
version?:stringProperties
readyTimeoutMs?:numberready() rejects and an error with reason: 'ready-timeout' is emitted; defaults to 10000.resetBody?:booleanhtml/body; defaults to true. Zeroes margin and padding, forces background: transparent, and pins color-scheme: normal — on a standalone visit too, and injected late enough to outrank the page's own body rules, so paint the feature's background on its root layout element instead.root?:string | HTMLElementversion?:stringcontract.version.request.Properties
◆ Types
type EventHandler = (data: unknown) => voidtype RequestHandler = (data: unknown) => unknownnone is the local default (opt-in security); production builds must pick v1 or v2.type SecurityProtocol = "none" | "v1" | "v2"● Variables
The host selects the mode; a feature declares which modes it supports in its
feature.config.* display.modes, and the generated shell composes exactly those.