Skip to content

App lifecycle

A Hailer App is a web page loaded in an iframe inside the Hailer frontend. The HailerApi client bridges your app and the host frame over postMessage. This page explains what happens between new HailerApi(...) and your first working call.

The handshake

When you construct the client it immediately tries to reach the host:

  1. Is this page inside an iframe? The SDK compares window.location to window.parent.location.
  2. If not in a frame (opened standalone), the app goes straight to outside mode: the SDK fetches the public app config via hailer.public.app.config() and calls your outside callback.
  3. If in a frame, the SDK broadcasts a register message (appApiVersion: '2') to every URL in allowedUrls. It then waits 100 ms for a reply:
    • Reply received → the SDK records the app id, workspace id, and host origin; registers the live listeners for settings, config, and signals; and calls connected.
    • No reply in 100 ms → the SDK assumes it's not really inside Hailer and falls back to outside mode (outside is called).

Because of the wait, the client is not ready the moment you construct it. Always make your first calls in connected (or after it fires).

Constructor options

Every field on the Options object is optional:

OptionTypeWhen it fires
connected() => voidOnce, when the host handshake succeeds and calls can be made.
outside(config?: any) => voidOnce, when the app is determined to be running standalone (outside Hailer).
error(error: Error) => voidOn errors (defaults to logging to the console).
settings(data: Settings) => voidOn init and whenever the user's UI settings change (theme, preferred languages).
config(config: any) => voidOn init and whenever the app config changes.
signals(signal: Signal) => voidFor each subscribed signal Hailer emits. See Signals.
permissions() => voidOn init and whenever a workspace.role.* change is emitted. Carries no data — call hailer.permission.map() to read the current values.
allowedUrlsstring[]Host URLs the SDK may hand-shake with. Defaults to all known Hailer instances.
publicBackendUrlstringPublic backend base URL for hailer.public.*. Defaults per host, else https://api.hailer.com.

Inside vs outside mode

Inside HailerOutside (standalone)
Triggerregister reply within 100 msNot in a frame, or no reply
Callbackconnectedoutside
Usable APIAll modules (subject to app scope)Only hailer.public.*
SessionCurrent Hailer userNone — public endpoints only

Design any app that should work logged-out around hailer.public.*, and treat everything else as available only after connected.

allowedUrls and the public backend

allowedUrls is the allow-list of host origins the SDK will complete a handshake with; by default it covers Hailer's production, staging, and local instances. If your app is embedded somewhere custom, pass your own list.

Once connected, the SDK picks the matching public backend URL for the host it's running in (used by hailer.public.*). You can override it with publicBackendUrl.

Reading connection state: info()

hailer.info() returns a synchronous snapshot of the connection:

ts
const { hostUrl, outside, workspaceId, config } = hailer.info();
FieldMeaning
hostUrlOrigin of the host Hailer frame (undefined until connected).
outsidetrue outside Hailer, false inside, null before detection completes.
workspaceIdThe workspace the app is locked to, if any (see Private vs workspace apps).
configThe app config, populated once the config callback has fired.

Next steps

Hailer Developer Documentation