npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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-bridge
import { 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 interactive

After initialization, communication is bidirectional:

  • Host -> Widget: set-variable, call-function
  • Widget -> Host: variable-changed, event, error, log