webdevpuneet.com

BroadcastChannel Cross-Tab Sync — Free Demo With Live Log

BroadcastChannel Cross-Tab Sync · Visualizers · Plain HTML, CSS & JS · Live preview

CategoryVisualizers

Copy & paste

Source Code

<section class="bcs-wrap">
  <span class="bcs-tag">broadcastchannel api · cross-tab sync</span>
  <h1>Cross-tab counter</h1>
  <p id="bcsStatus">Open this page in a second tab, then click the buttons below — the count stays in sync across both.</p>

  <div class="bcs-counter">
    <button class="bcs-step" id="bcsDec">−</button>
    <div class="bcs-count" id="bcsCount">0</div>
    <button class="bcs-step" id="bcsInc">+</button>
  </div>

  <div class="bcs-actions">
    <button class="bcs-btn" id="bcsSimBtn">Simulate a second tab (same page)</button>
    <button class="bcs-btn ghost" id="bcsReset">Reset</button>
  </div>

  <div class="bcs-log-head">Message log</div>
  <ul class="bcs-log" id="bcsLog"></ul>
</section>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Real BroadcastChannel messaging
postMessage between same-origin contexts.
No server involved
Pure browser-to-browser delivery.
Self-exclusion by design
A channel never hears its own messages.
Same-page simulated tab
A second independent channel instance for a one-tab demo.
Bidirectional live log
Every sent and received message is timestamped.
storage-event fallback
Works even without BroadcastChannel support.
Per-tab identifier
Random tabId labels each message's origin.
Clear active-mode messaging
States which sync mechanism is in use.

About this UI Snippet

BroadcastChannel Cross-Tab Sync — Real Messages Between Tabs

Screenshot of the BroadcastChannel Cross-Tab Sync snippet rendered live

BroadcastChannel is the browser's native publish/subscribe channel between same-origin browsing contexts — tabs, windows, iframes, and workers can all join a channel by name and send each other messages with postMessage, with no server round-trip involved. This snippet demonstrates it with the simplest possible payload: a shared counter that stays in sync everywhere the page is open.

How the sync actually works

Every instance of the page opens new BroadcastChannel('bcs-demo-counter'). Clicking + or − updates the local count and calls channel.postMessage({ type, value, tabId }); every *other* open instance receives that message in its channel.onmessage handler (a channel never receives its own messages) and updates its own count to match. There's no polling and no server — the browser delivers the message directly to every other same-origin context subscribed to that channel name, typically within milliseconds.

Why one tab can't prove this on its own

The whole point of BroadcastChannel is *cross*-tab communication, so a single open tab can't visually demonstrate it — you need a second real tab open to the same page to see a message arrive from outside. This snippet makes that obvious with instructions right in the UI, but also includes a same-page "simulate a second tab" button, which opens a genuinely independent second BroadcastChannel instance inside the same document. The browser treats it identically to a second tab — it's a separate object with its own onmessage handler — so you can watch a message actually leave one channel instance and arrive at another without opening a second window.

A live log of both directions

Every send and every receive is written to a timestamped log, labeled with which "tab" it came from, so the direction of each message is never ambiguous — useful for actually seeing the asynchronous, fire-and-forget nature of postMessage.

Fallback for unsupported browsers

BroadcastChannel is broadly supported in evergreen browsers but missing from a handful of older or embedded webviews. When 'BroadcastChannel' in window is false, the snippet falls back to the classic localStorage storage-event trick: writing to localStorage in one tab fires a storage event in every *other* same-origin tab (never the writer), which is a well-known, near-universally-supported way to achieve the same cross-tab notification. The status text always states plainly which mode is active. Pair this with a web locks tab coordinator for a fuller multi-tab coordination toolkit, or a live visitor counter for a related shared-state dashboard idea.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA counter with +/− buttons renders.
  2. 2
    Open the page in a second tabSame URL, same origin.
  3. 3
    Click + or − in either tabThe count updates in both tabs instantly.
  4. 4
    Watch the message logSent and received messages are both logged.
  5. 5
    No second tab handy?Click "Simulate a second tab" to see the flow on one page.
  6. 6
    ResetBroadcasts a reset to every open instance.

Real-world uses

Common Use Cases

Multi-tab authentication
Sync login and logout across every open tab with BroadcastChannel, which needs no server involvement at all.
Shopping carts
Keep shopping cart contents consistent everywhere, remembering that a channel never receives its own messages by design.
Theme and preference sync
Propagate dark mode toggles instantly to other tabs, with a storage event fallback for browsers lacking the API.
Tab coordination
Pair with a web locks tab coordinator when one tab must lead while all tabs share state.
Presence demos and notification dismissal
Simulate presence like a live visitor counter, or dismiss an alert everywhere it appears, using a same-page second channel to demo with one tab.
Related: Database Connection Pool Monitor Tile
See the Database Connection Pool Monitor Tile for a related dashboards pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

BroadcastChannel is specifically for communication BETWEEN separate browsing contexts, and a channel never receives its own posted messages — only other instances subscribed to the same channel name do. A single tab has only one instance, so there's no "other side" to receive anything. Opening a second tab to the same page, or using the built-in "simulate a second tab" button, creates that second instance.

It creates a second, fully independent BroadcastChannel object on the same channel name within the same page. The browser treats this exactly like a second tab's channel — it has its own onmessage handler and receives messages posted by the first instance (and vice versa) — so you can observe real cross-instance delivery without leaving the page.

The snippet checks `BroadcastChannel` in window at load and, if false, switches to a localStorage-based fallback: writing a value to localStorage fires a storage event in every other same-origin tab (but never the tab that wrote it), which has been supported far longer than BroadcastChannel and achieves the same cross-tab notification, just with a slightly different payload shape.

No — BroadcastChannel is strictly same-origin, matching the page's full origin (protocol, host, and port). It cannot be used to message a different domain or even a different port on the same host; for cross-origin communication you would need something like postMessage on a window reference or a server-mediated channel instead.

Create the BroadcastChannel instance once in a mount effect (store it in a ref so it survives re-renders), post messages from your event handlers, and update component state from the onmessage callback. Close the channel with channel.close() in the cleanup function to avoid leaking a listener when the component unmounts.