Today WebView Bridge
Web SDK

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:

MemberReturnsNotes
isAvailable()booleantrue only inside a Today native WebView
platformPlatform'ios' | 'android' | 'macos' | 'windows' | 'web', resolved synchronously
track(event, properties?)voidFire-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:

MethodNo-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:

  1. Single channel, capability dispatch. One native handler, discriminated by a type field. New capabilities are additive and never break older hosts.
  2. Safe degradation. Absence of a host is a normal state, not an error.
  3. Promise-based everywhere. The same API shape over the iOS reply handler and the Android shim.
  4. The web owns request decoration. The host cannot inject headers into fetch / XHR it never sees, so the web pulls headers and attaches them.
  5. Authorization is never assumed. Its presence depends on the current URL trust domain and login state; treat it as optional.

On this page