Overview
The @today/webview-bridge client — what it is and how the web side is meant to use it.
@today/webview-bridge is the web-side client for the Today WebView Bridge. It
wraps the raw native channel in a small, typed, promise-based API and degrades
safely when no host is present (desktop browsers, Android Chrome, any non-app
WebView).
Install
@today/webview-bridge is a workspace package. Add it to the consuming app:
// package.json
{
"dependencies": {
"@today/webview-bridge": "workspace:*",
},
}The client
A single factory returns the client. Create it once per document and share it.
import { createWebViewBridge } from '@today/webview-bridge'
export const bridge = createWebViewBridge()The client exposes five methods plus one convenience helper:
| Member | Returns | Notes |
|---|---|---|
isAvailable() | boolean | true only inside a Today native WebView |
platform | Platform | 'ios' | 'android' | 'macos' | 'windows' | 'web', resolved synchronously |
track(event, properties?) | void | Fire-and-forget analytics |
getHeaders() | Promise<Record<string, string>> | Headers to attach to your own requests |
refreshToken() | Promise<RefreshTokenResult> | Force a token refresh; rejects on failure |
establishSession(options?) | Promise<boolean> | Host mints the session cookie natively; never returns the bearer to JS |
fetch(input, init?) | Promise<Response> | getHeaders + 401-refresh-retry, in one call |
See the API Reference for the full signatures and the Authenticated fetch page for the recommended request pattern.
Safe degradation is the default
Every method is defined whether or not a host exists. The client never throws because the bridge is missing — it returns an inert result instead:
| Method | No-host behaviour |
|---|---|
isAvailable() | false |
track() | no-op |
getHeaders() | resolves to {} (never rejects, even on a transport fault) |
refreshToken() | rejects with BridgeUnavailableError |
establishSession() | resolves false (no host / unsupported / failure) |
fetch() | falls back to the platform fetch, no injected headers |
This means you can write one code path that works in the app and in a plain
browser. Guard only the behaviour that genuinely requires the host (for example,
gating a feature on isAvailable()), not every call site.
Design principles
The SDK is deliberately thin. Five rules shape it:
- Single channel, capability dispatch. One native handler, discriminated by
a
typefield. New capabilities are additive and never break older hosts. - Safe degradation. Absence of a host is a normal state, not an error.
- Promise-based everywhere. The same API shape over the iOS reply handler and the Android shim.
- The web owns request decoration. The host cannot inject headers into
fetch/XHRit never sees, so the web pulls headers and attaches them. Authorizationis never assumed. Its presence depends on the current URL trust domain and login state; treat it as optional.