📡 BroadcastChannel live

Two simulated browser tabs — both subscribed to the same BroadcastChannel('demo'). Type a message in Tab A and watch it arrive in Tab B in real time. The sender never receives its own message.

1 Send a message between tabs
Tab A — sender
Message to broadcast
Quick scenarios
no messages sent yet
Tab B — receiver
Received messages
Waiting for messages from Tab A…

Tab B called channel.onmessage = (e) => … — it gets every message Tab A sends.

2 The code behind this demo
// Tab A — open a channel and send const channel = new BroadcastChannel('demo'); channel.postMessage({ type: 'LOGOUT' }); // Tab B — same channel name, receives all messages const channel = new BroadcastChannel('demo'); channel.onmessage = (event) => { console.log(event.data); // { type: 'LOGOUT' } }; // Clean up when done channel.close();

Any tab, worker, or iframe on the same origin that opens a channel with the same name is part of the group. The sender never receives its own messages.

3 BroadcastChannel vs the localStorage trick
Aspect localStorage + storage event BroadcastChannel
Sending localStorage.setItem(key, JSON.stringify(data)) channel.postMessage(data)
Serialization Manual — must JSON.stringify and JSON.parse None — structured clone handles it
Cleanup Must removeItem immediately (triggers a second event) No side effects — just send
Event filtering Must check event.key and event.newValue Only receives messages from the same channel name
Data types Strings only Any structured-cloneable value (objects, arrays, Date, Map…)
Same-tab detection Sender receives its own events — must add a timestamp filter Sender never receives its own messages
4 What you can send (structured clone)
// ✅ All of these work with postMessage: channel.postMessage({ type: 'UPDATE', count: 42 }); // object channel.postMessage([1, 2, 3]); // array channel.postMessage(new Date()); // Date channel.postMessage(new Map([['key', 'value']])); // Map channel.postMessage(new Set([1, 2, 3])); // Set // ❌ These throw a DataCloneError: channel.postMessage(() => {}); // functions channel.postMessage(document.body); // DOM nodes