frame-bridge
Open source · MIT

Type-safe messaging between browser windows

Send requests and receive responses between iframes, tabs, and popups. Works with vanilla JS or React. Three transport mechanisms, one unified API.

Vanilla JS / TypeScript

As simple as calling a function

The bridge handles message correlation, timeouts, transport selection, and error handling. You just send and receive.

npm i @mhanzelka/frame-bridge
// parent.ts
const parent = createBridge<Messages>({
    channelName: "my-channel",
    role: "parent",
    enabled: ["broadcast-channel"],
});

await parent.open();
const reply = await parent.send({ type: "ping", value: 1 });
// reply: { type: "pong", value: 2 }

// child.ts
const child = createBridge<Messages>({
    channelName: "my-channel",
    role: "child",
    enabled: ["broadcast-channel"],
});

await child.open();
child.onMessage(async (msg) => {
    if (msg.type === "ping")
        return { type: "pong", value: msg.value + 1 };
});
function App() {
    return (
        <BridgeProvider
            open={true}
            channelName="my-channel"
            role="parent"
            enabledTransports={["broadcast-channel"]}
        >
            <Controls />
        </BridgeProvider>
    );
}

function Controls() {
    const bridge = useBridge<Messages>();
    const state = useBridgeState();

    return (
        <button onClick={() => bridge.send({ type: "ping", value: 1 })}>
            {state.state === "open" ? "Send" : "Connecting…"}
        </button>
    );
}

React

First-class React integration

Wrap your tree with BridgeProvider, access the bridge anywhere with useBridge(), subscribe to connection state with useBridgeState().

npm i @mhanzelka/react-frame-bridge

Type-safe by default

Define your message types once. Get autocomplete and type checking on both sides of the bridge.

Three transports

BroadcastChannel for same-origin, postMessage for cross-origin iframes, MessageChannel for high-throughput dedicated channels.

React integration

BridgeProvider, useBridge, useBridgeState, and IframeBridgeHost. Drop-in hooks that follow React patterns.

Built-in DevTools

Floating debug panel shows live messages, connection state, and request/response pairs with timing.

Choose your transport

Enable multiple transports and the bridge picks the best available one per message.

TransportBrowser APIBest forCross-origin
broadcast-channelBroadcastChannelSame-origin tabs, iframes, popupsSame-origin only
post-message-channelwindow.postMessageCross-origin iframes
message-channelMessageChannelHigh-throughput dedicated channel

Ready to bridge the gap?

Three packages. Zero runtime dependencies in the core. Works in any modern browser.