PRO

Effect Browser Peer Channel

A popup, a hidden iframe, or a dedicated worker as one scoped Effect Stream, built on [email protected] and @effect/platform-browser. The message listener is attached by an acquireRelease step before the context is opened, because a Stream subscribes only when it is run: forking a drain of BrowserStream.fromEventListenerWindow leaves zero listeners attached when the next statement executes, so the ordinary listen-then-open fix does not actually close the boot race. Every event is then pinned to that one peer by both source and origin, so the party line that is window.onmessage becomes a channel, and each payload is decoded through a schema at the edge, so a malformed frame fails the channel instead of a reducer. The context is acquired inside the stream's own scope, so completion, failure, interruption, and the opener page unloading all release it on one path, and a popup the user closed or a worker that crashed on boot becomes a typed PeerGone rather than a stream that waits forever. Includes a one-shot askPeer that sends its request on the back of the peer's first message, since the child is running the same race in the other direction, and closes the context with the same step that produces the answer.

Install
npx shadcn@latest add https://ui.aryank.space/r/effect-browser-peer-channel.json

Installs from ui.aryank.space. To add it by hand, copy the files in Files below, or register the @compronents namespace via the docs.

Visualization
listener
open popup
Window | null
popup posts ready
MessageEvent
attach listener
void
const popup = open(url); window.addEventListener("message", onMessage)

The ordinary shape. The popup boots in the gap between the two statements and posts ready into a window that is not listening yet, and the platform drops an event nobody is waiting for. Nothing throws and nothing is logged: the bug lives in the semicolon, and it only shows up on a cold cache or a slow machine.

Files

Dependencies