Architecture

How the Widget SDK isolates styles, authenticates users, and communicates between your page and the widget iframe.

Shadow DOM

Each widget element creates a closed Shadow Root. This means the widget's internal DOM and styles are completely encapsulated - your page's CSS cannot leak into the widget, and the widget's styles cannot affect your page.

This makes the SDK safe to use alongside any CSS framework (Tailwind, Bootstrap, Material UI, etc.) without conflicts. The closed mode also prevents external JavaScript from accessing the Shadow Root via element.shadowRoot, providing an additional layer of isolation.

Customer page DOM
└── <div id="returning-ai-widget-{id}">
    └── <rai-widget>
        └── Shadow Root [closed]
            ├── <style>       CSS scoped here
            ├── <div class="rai-loader">
            ├── <div class="rai-error">
            └── <iframe>      widget content

Auth Flow

When the widget element connects to the DOM, it checks for the auth-url attribute. If present, the SDK initiates the token authentication flow:

  1. Page loads - the custom element is registered and connected to the DOM.
  2. Check auth-url - if the attribute is set, the SDK POSTs to your auth endpoint with the user's email in headers.
  3. Authenticate - your backend calls the Returning.AI API to obtain access and refresh tokens, then returns them to the SDK.
  4. Create iframe - the SDK constructs the widget iframe URL and appends it to the Shadow Root.
  5. Send token - once the iframe loads, the SDK sends the access token via postMessage so the widget can make authenticated API calls.

If auth-url is not set, the widget loads using attribute authentication (reading data-* attributes from the element) and skips the token fetch in steps 2–3.

Token Storage

The SDK manages two tokens with different storage strategies to balance security and user experience.

TokenStorageLifetimePurpose
Access tokenMemory only~5 minutesShort-lived credential sent to the iframe for API calls. Never written to disk.
Refresh tokenlocalStorage7 daysUsed to obtain new access tokens without re-authenticating the user.

postMessage Protocol

The SDK and the widget iframe communicate via window.postMessage. All messages use a typed type field for routing.

Messages sent to iframe

TypePayloadDescription
RETURNINGAI_WIDGET_TOKEN{ token, widgetId }Delivers the access token to the iframe after authentication.
RETURNINGAI_WIDGET_REFRESH{ token, widgetId }Sends a refreshed access token before the current one expires.
RETURNINGAI_WIDGET_LOGOUT{ widgetId }Instructs the iframe to clear its session state.

Messages received from iframe

TypePayloadDescription
RETURNINGAI_WIDGET_REQUEST_TOKEN{ widgetId }Iframe requests an access token (sent on iframe load).
RETURNINGAI_WIDGET_READY{ widgetId }Widget has finished initialising and is interactive.
RETURNINGAI_WIDGET_HEIGHT{ height }Reports the widget content height for auto-sizing.
RETURNINGAI_WIDGET_ERROR{ message, code? }Reports an error from within the iframe.

Browser Support

The SDK requires custom elements v1 and Shadow DOM v1 support. All modern browsers are supported.

BrowserMinimum Version
Chrome67+
Firefox63+
Safari13+
Edge79+ (Chromium)
Opera54+