Appearance
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:
- Is this page inside an iframe? The SDK compares
window.locationtowindow.parent.location. - 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 youroutsidecallback. - If in a frame, the SDK broadcasts a
registermessage (appApiVersion: '2') to every URL inallowedUrls. 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 (
outsideis called).
- Reply received → the SDK records the app id, workspace id, and host origin; registers the live listeners for settings, config, and signals; and calls
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:
| Option | Type | When it fires |
|---|---|---|
connected | () => void | Once, when the host handshake succeeds and calls can be made. |
outside | (config?: any) => void | Once, when the app is determined to be running standalone (outside Hailer). |
error | (error: Error) => void | On errors (defaults to logging to the console). |
settings | (data: Settings) => void | On init and whenever the user's UI settings change (theme, preferred languages). |
config | (config: any) => void | On init and whenever the app config changes. |
signals | (signal: Signal) => void | For each subscribed signal Hailer emits. See Signals. |
permissions | () => void | On init and whenever a workspace.role.* change is emitted. Carries no data — call hailer.permission.map() to read the current values. |
allowedUrls | string[] | Host URLs the SDK may hand-shake with. Defaults to all known Hailer instances. |
publicBackendUrl | string | Public backend base URL for hailer.public.*. Defaults per host, else https://api.hailer.com. |
Inside vs outside mode
| Inside Hailer | Outside (standalone) | |
|---|---|---|
| Trigger | register reply within 100 ms | Not in a frame, or no reply |
| Callback | connected | outside |
| Usable API | All modules (subject to app scope) | Only hailer.public.* |
| Session | Current Hailer user | None — 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();| Field | Meaning |
|---|---|
hostUrl | Origin of the host Hailer frame (undefined until connected). |
outside | true outside Hailer, false inside, null before detection completes. |
workspaceId | The workspace the app is locked to, if any (see Private vs workspace apps). |
config | The app config, populated once the config callback has fired. |
Next steps
- Private vs workspace apps — what
workspaceIdimplies for every call. - Signals — subscribe to live changes.
- Reference — every module and method.