Works with any backend npm install Zero dependencies

Aggregate progress from every browser tab via BroadcastChannel

Extends the existing crossTab coordination so a "manager" tab can subscribe to progress + state events from every sibling tab. The aggregator tab doesn't need its own uploader - it just listens via MultipleUpload.subscribeAllTabs() and renders rows for each active tab. Genuinely unique vs Uppy / FilePond / Dropzone / FineUploader: none expose cross-tab progress aggregation.

Live aggregator (this tab acts as manager):

Also-acts-as-uploader in this tab:

Try it:
  1. Open this demo in 2 or 3 separate tabs.
  2. Pick files in one tab, hit upload.
  3. Watch the dashboard at the top - it shows progress rows for every tab, including the others.
  4. Close one of the tabs; the dashboard auto-removes its row on the tabBye event.
API surface
// Subscribe - no uploader needed in this tab
const unsub = MultipleUpload.subscribeAllTabs((msg) => {
 switch (msg.type) {
 case 'tabHello': console.log('Tab joined:', msg.tabId); break;
 case 'tabBye': console.log('Tab left:', msg.tabId); break;
 case 'progress': updateProgressRow(msg); break;
 case 'taskState': updateStateRow(msg); break;
 }
}, 'my-app-channel');

// Convenience widget (renders into any DOM target):
const dashboard = MultipleUpload.createMultiTabDashboard('#manager-view', {
 channel: 'my-app-channel',
 keepCompleted: false, // remove finished rows after dismissMs
 dismissMs: 4000
});

// Cleanup:
unsub();
dashboard.destroy();
Broadcast message shapes
// On task progress (throttled 250ms per task):
{ type: 'progress', tabId, taskId, fileName, fileSize, uploadedBytes,
 progress, speed, eta, status, ts }

// On task state change (added / paused / completed / failed / cancelled):
{ type: 'taskState', tabId, taskId, fileName, fileSize, status, prevStatus, ts }

// On tab open / close:
{ type: 'tabHello', tabId, ts }
{ type: 'tabBye', tabId, ts }
How it works
  • Same channel as crossTab lock coordination: reuses the existing BroadcastChannel; just adds new message types alongside lock / unlock / probe.
  • Throttled progress: uploaders emit at most 1 progress broadcast per task per 250ms - keeps the channel quiet even on chunked uploads.
  • Listen-only tabs work: a dashboard tab without its own uploader still receives messages - the static listener manages its own BroadcastChannel.
  • Same-origin only: BroadcastChannel is sandboxed to a single origin - cross-app leakage isn't possible.
  • tabHello on init: uploaders announce themselves the moment they boot, so the dashboard sees them even if no uploads have started yet.
  • tabBye on unload: the existing pagehide / beforeunload handler now broadcasts a goodbye message so dashboards drop the row instantly.
Use cases
  • Admin / monitoring dashboards: show every active user upload across tabs.
  • "Don't close that tab" warnings: a manager tab can detect a user closing their upload-in-flight tab and warn them.
  • Federated progress UI: aggregate progress from background-tab uploads into the foreground tab's nav bar.
  • Test harnesses: open N tabs all uploading; aggregator-tab confirms throughput / failure rates.