Skip to content

Deepak-Kharah/blog-inter-tab-communication

Repository files navigation

Inter-Tab Communication Demo

A simple project showcasing real-time inter-tab communication using browser's Broadcast Channel API and PostMessage API. This project features a custom-built advanced-broadcast-message tool that extends the browser's native Broadcast Channel API with async/await support, enabling promise-based communication patterns between browser tabs.

This demo illustrates how multiple browser tabs can stay synchronized with a single source of truth, where one tab acts as the primary hub performing all actions and broadcasting state changes to other tabs.

🎯 Overview

This demo implements a primary hub pattern for inter-tab communication, where:

  • Primary Tab: Acts as the single source of truth, performs all actions, and stores all state updates
  • Secondary Tabs: Automatically sync their state with the primary tab through broadcast messages
  • Real-time Sync: Changes made in the primary tab are instantly reflected across all open tabs

We demonstrate this pattern using a simple Content Management System (CMS) use case, where form changes in one tab are immediately visible in preview panes across all tabs.

🏗️ Architecture

Communication Channels

The project uses two communication mechanisms:

  1. Advanced Broadcast Message (advanced-broadcast-message): A custom-built tool that extends the browser's native Broadcast Channel API with async/await support. This enables promise-based, request-response patterns for inter-tab communication, making it easier to handle state synchronization and initialization requests.

  2. PostMessage API (advanced-post-message): Enhanced postMessage API for iframe communication

Key Innovation: Async/Await Broadcast Messages

The native Browser Broadcast Channel API only supports one-way message passing. This project uses a custom advanced-broadcast-message tool that introduces:

  • Promise-based communication: Send messages and await responses
  • Request-response pattern: Request initial state and receive it asynchronously
  • Type-safe messaging: Full TypeScript support for message payloads
  • Error handling: Built-in error suppression and promise rejection handling

This allows for cleaner, more intuitive code patterns like:

// Request initial state and await the response
const response = await advBroadcastMessage
  .send<OnInitResponsePayload>(COMMUNICATION_EVENTS.INIT);

// Handle the response
setState(response.cmsData);

Primary Hub Pattern

┌─────────────────┐
│   Primary Tab   │ ← Single Source of Truth
│   (CMS Form)    │
└────────┬────────┘
         │
         ├─── Broadcast Channel ───┐
         │                          │
         │                          ▼
    ┌────┴────┐              ┌─────────────┐
    │  Tab 2  │              │    Tab 3     │
    │ (Sync)  │              │   (Sync)     │
    └─────────┘              └─────────────┘

How It Works

  1. Initialization: When a new tab opens, it requests the current state from the primary tab via broadcast messages
  2. State Updates: When the primary tab makes changes, it broadcasts updates to all listening tabs
  3. Synchronization: Secondary tabs receive updates and automatically sync their local state
  4. Iframe Communication: The preview pane (iframe) receives updates via postMessage API

🚀 Getting Started

Prerequisites

  • Node.js 18+
  • pnpm (or npm/yarn/bun)

Installation

# Install dependencies
pnpm install

Development

# Start the development server
pnpm dev

Open http://localhost:6576 in your browser.

Building for Production

# Build the application
pnpm build

# Start production server
pnpm start

📖 Usage

Basic Demo Flow

  1. Open the Primary Tab: Navigate to http://localhost:6576 - this is your primary hub
  2. Open Secondary Tabs: Open http://localhost:6576/new-tab in additional browser tabs
  3. Make Changes: Edit the CMS form fields in the primary tab
  4. Observe Sync: Watch as changes instantly appear in all secondary tabs' preview panes

Pages

  • / - Primary tab with CMS form and preview pane
  • /new-tab - Secondary tab that syncs with the primary tab
  • /user-website - Preview iframe that displays the CMS content

🔧 Technical Implementation

Advanced Broadcast Message Tool

This project showcases a custom advanced-broadcast-message library that enhances the browser's Broadcast Channel API. Unlike the native API which only supports one-way messaging, this tool enables:

  • Async/await patterns: Send messages and await responses using promises
  • Request-response flow: Request data from other tabs and receive responses
  • Type safety: Full TypeScript support with typed payloads and responses
  • Event listeners: Register handlers that can return responses to requests

Communication Events

The project uses a structured event system:

  • INIT: Request initial state from the primary tab (uses async/await pattern)
  • ON_CHANGE: Broadcast state changes to all tabs (one-way broadcast)

Key Components

Communication Channel (lib/communication-channel/)

  • communication-channel.ts: Initializes broadcast and postMessage managers
  • communication-channel.constant.ts: Defines channel IDs and event names
  • communication-channel.type.ts: TypeScript types for payloads

CMS Module (lib/cms-module/)

  • cms-modle.constant.ts: Default CMS data and layout options
  • cms-module.type.ts: TypeScript types for CMS data structure

Components

  • CMSForm: Primary form component that acts as the source of truth
  • PreviewPane: Displays the preview iframe
  • NewTabPage: Secondary tab that syncs with primary tab

State Flow

The async/await pattern enables clean request-response flows:

Primary Tab (CMSForm)
    │
    ├─→ handleChange()
    │   │
    │   ├─→ advPostMessageParent.send() → iframe (PreviewPane)
    │   └─→ advBroadcastMessage.send() → all tabs (one-way broadcast)
    │
    └─→ advBroadcastMessage.on('INIT', async () => {
        return { cmsData: formData }; // Returns promise response
    })

Secondary Tab (NewTabPage)
    │
    ├─→ await advBroadcastMessage.send('INIT') → requests & receives state
    │   (Uses async/await to get response from primary tab)
    │
    └─→ advBroadcastMessage.on('ON_CHANGE') → receives updates

Preview Iframe (UserWebsite)
    │
    ├─→ await advPostMessageChild.send('INIT') → requests state
    └─→ advPostMessageChild.on('ON_CHANGE') → receives updates

Example: Async/Await in Action

Here's how the advanced broadcast message tool enables async/await patterns:

Primary Tab (listens for INIT requests):

advBroadcastMessage?.on<undefined, OnInitResponsePayload>(
  COMMUNICATION_EVENTS.INIT,
  async () => {
    return { cmsData: formData }; // Returns response
  }
);

Secondary Tab (requests initial state):

const response = await advBroadcastMessage
  ?.send<OnInitResponsePayload>(COMMUNICATION_EVENTS.INIT);
// response.cmsData is now available

Tools I built and used in this project

  • advanced-broadcast-message: Custom-built tool that extends the browser's Broadcast Channel API with async/await support, enabling promise-based request-response patterns for inter-tab communication
  • advanced-post-message: Enhanced postMessage API for iframe communication enabling promise-based request-response patterns for inter-tab communication

🔍 Code Structure

blog-inter-tab-communication/
├── app/
│   ├── page.tsx              # Primary tab (CMS form + preview)
│   ├── new-tab/
│   │   └── page.tsx          # Secondary tab (syncs with primary)
│   └── user-website/
│       └── page.tsx          # Preview iframe content
├── components/
│   ├── CMSForm/              # CMS form component
│   ├── PreviewPane/          # Preview pane wrapper
│   └── ui/                   # Reusable UI components
├── lib/
│   ├── communication-channel/ # Communication utilities
│   └── cms-module/           # CMS data types and constants
└── package.json

💡 Use Cases

This pattern is useful for:

  • Multi-tab applications: Keep state synchronized across tabs
  • CMS/Admin panels: Edit in one tab, preview in others
  • Real-time dashboards: Share data across multiple views
  • Collaborative tools: Broadcast changes to all participants
  • Development tools: Live preview across multiple windows

🧪 Testing the Demo

  1. Open the primary tab at http://localhost:6576
  2. Open 2-3 additional tabs at http://localhost:6576/new-tab
  3. Make changes to the CMS form in the primary tab
  4. Observe real-time updates in all secondary tabs
  5. Try opening tabs in different browser windows to see cross-window communication

📚 Learn More

📝 License

This project is for demonstration purposes.


🛠️ About the Advanced Broadcast Message Tool

This project demonstrates a custom advanced-broadcast-message library that solves a key limitation of the native Browser Broadcast Channel API: the lack of async/await support.

The native API only supports one-way message broadcasting, making it difficult to implement request-response patterns. This custom tool adds:

  • Promise-based messaging with async/await
  • Request-response communication patterns
  • Type-safe message handling
  • Error handling and suppression

This enables cleaner, more intuitive inter-tab communication patterns that feel natural in modern JavaScript/TypeScript codebases.


Built with Next.js and a custom advanced broadcast messaging tool.

About

This demo showcases how to use advanced broadcast messaging to enable real-time inter-tab communication. In this example, one browser tab acts as the primary hub and single source of truth, performing all actions and storing updates. Other tabs automatically sync their state with the primary tab through broadcast messages.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors