ui/ doesn’t run on its own page — it runs inside the merchant’s Sentralbee dashboard: a web
iframe on desktop, a native WebView on mobile. That means two things the host has to tell you. Which theme
the merchant is using, so you don’t flash white in a dark dashboard. Where the safe area is, so your buttons
aren’t under a phone’s notch. And it means you need a way to prove which workspace is looking at you.
The host hands all three over a small postMessage bridge. You don’t touch the bridge directly — you read it
through three hooks from @sentralbee/app-sdk/react, and the same code works in the iframe and the
WebView. The host injects a shim that routes messages to native, so you write it once.
Tell the host you’re ready
Callready() once, after your component mounts:
Match the merchant’s theme
useHostTheme() returns 'light' or 'dark', and it stays in sync: when the merchant flips their dashboard
to dark mode, this re-renders with the new value. Before the host answers, it makes a sensible first guess
from the ?theme= param and the OS setting, so you don’t flash the wrong colours on first paint.
Respect the safe area
On a phone, part of the screen is taken up by the notch and the home indicator.useSafeArea() returns the
insets the host wants you to keep clear, in pixels:
0, so this costs you nothing there and does
the right thing on mobile. If you’d rather drive your styling from CSS variables, push the numbers into custom
properties yourself — the hook gives you plain values to do whatever you like with.
Get a session token, and call your own backend
useSessionToken() is the important one. It asks the host for a short-lived session token and gives you
back its loading state:
The token is not for reading data on its own. It’s a Bearer credential for calls to your own app’s
backend. Your UI calls
/api/* on your own origin with the token attached, and your backend verifies it and
derives the workspace from it:
workspace is decoded straight from the token ({ id, name, domain }) so you can render “Acme Store” in
your header without a round-trip. It’s for display only — never branch your authorization on it. Your
backend does that from the verified token.Why a URL token is safe in dev but not in production
In local dev and in the native WebView, the session arrives as a?token= on the embed URL — that’s how
sentralbee dev hands you a live session with no real platform. Inside the production dashboard iframe, that
same ?token= param is ignored. The token there comes only from the host, over the bridge.
That’s deliberate. A framed embed that trusted a URL token could be handed a forged one by whatever page
linked to it (session fixation). So the SDK accepts a URL token only when your app is top-level — never
when it’s framed. You get the convenience in dev and the safety in production, with no code change on your
side.
Where to next
- Calling the API — what your backend does with the session token and the stored key.
- Concepts & lifecycle — the trust model behind session and provision tokens.
- The manifest — declare your embed and the scopes it needs.

