@gradientzero/frame-bridge
v1.0.3
Published
Lightweight iframe-to-parent communication bridge
Readme
@gradientzero/frame-bridge
Lightweight communication bridge for interactive widgets embedded in iframe sandboxes. Enables bidirectional communication between an iframe and its host application through structured postMessage messaging.
What it does
The runtime API (init()) runs inside the iframe and provides a simple interface for:
- Variables — Declare typed state (number, string, boolean) that the host application can read, display, and modify. Changes are automatically synchronized in both directions.
- Functions — Register callable functions with typed parameters that the host application can invoke (e.g., reset a simulation, trigger an animation).
- Events — Emit named events to the host application (e.g., "level-complete", "threshold-reached") for the host to react to.
The host application receives a manifest of all declared variables, functions, and events during initialization, enabling it to build dynamic UIs (e.g., property panels, rule builders) without prior knowledge of the widget's capabilities.
The library also exports TypeScript types and protocol constants for the host side to handle incoming messages and build its own integration layer.
Installation
Browser (via esm.sh):
<script type="module">
import { init } from 'https://esm.sh/@gradientzero/frame-bridge@1';
</script>npm (for bundlers):
npm install @gradientzero/frame-bridgeimport { init } from '@gradientzero/frame-bridge';Quick Start
import { init } from 'https://esm.sh/@gradientzero/frame-bridge@1';
const bridge = init();
// Declare variables — the host can see and modify these
const temperature = bridge.variable('temperature', {
type: 'number',
default: 20,
label: 'Temperature (°C)',
min: 0,
max: 100,
});
// Declare functions — the host can call these
bridge.function('reset', { params: [], label: 'Reset' }, () => {
temperature.set(20, { immediate: true });
});
// Declare events — the host receives these
bridge.events(['threshold-reached']);
// Read and write variables
temperature.get(); // 20
temperature.set(42); // notifies host
// React to host-initiated changes
temperature.subscribe((value) => {
document.getElementById('display').textContent = `${value}°C`;
});
// Emit events to the host
bridge.emit('threshold-reached', { value: temperature.get() });API
init(options?): Bridge
Initialize the bridge. Must be called once at the top level of the widget.
| Option | Type | Default | Description |
| ---------- | --------- | ------- | ------------------------------------------------ |
| debounce | number | 0 | Default debounce delay (ms) for variable updates |
| debug | boolean | false | Enable diagnostic logging |
bridge.variable(name, options): VariableHandle
Declare a variable. Must be called synchronously after init().
Options:
| Field | Type | Required | Description |
| ----------------- | ----------------------------------- | -------- | ---------------------------------------------------------------------------------- |
| type | 'string' \| 'number' \| 'boolean' | Yes | Variable type |
| default | any | No | Default value |
| debounce | number | No | Per-variable debounce override (ms) |
| ...extra fields | | No | Metadata forwarded to host (e.g., label, min, max, description, options) |
VariableHandle methods:
| Method | Description |
| --------------------- | --------------------------------------------------------------------------- |
| get() | Read the current value |
| set(value, opts?) | Update the value. Pass { immediate: true } to bypass debounce |
| subscribe(callback) | Listen for changes (from host or internal). Returns an unsubscribe function |
| dispose() | Clean up subscriptions |
bridge.function(name, options, handler)
Register a function that the host application can call with typed arguments.
bridge.function(
'setLevel',
{
params: [{ name: 'level', type: 'number' }],
label: 'Set Level',
},
(level) => {
currentLevel = level;
},
);bridge.events(names)
Declare events that the widget can emit to the host.
bridge.emit(name, data?)
Emit a named event to the host application.
bridge.waitUntil(promise, opts?)
Register async work (e.g., asset loading) that must complete before the bridge signals readiness. The host receives progress updates.
bridge.waitUntil(loadImage('sprite.png'), { label: 'sprite' });bridge.reportError(error)
Report an error to the host for display or logging.
Protocol
The bridge uses a structured postMessage protocol with a three-step handshake:
Iframe (widget) Host application
| |
|--- init (manifest) --------------->| declares variables, functions, events
| |
|<-- init-ack (overrides) -----------| host sends stored configuration
| |
|--- ready ------------------------->| widget is interactiveAfter initialization, communication is bidirectional:
- Host -> Widget:
set-variable,call-function - Widget -> Host:
variable-changed,event,error,log
