Intro
This tutorial builds two Custom Apps that talk to each other in real time using App Broadcasting. You’ll create:
- Selector App — a data table that publishes a
selection:changedmessage whenever a user clicks a row - Detail App — a panel that subscribes to
selection:changedand shows details for the selected record
- Declare broadcast channels in
manifest.json - Publish and subscribe with
domo.broadcast()anddomo.onBroadcast() - Sync current state when an app mounts late (the bus keeps no history)
- Filter messages by source with
domo.onBroadcastFrom()
Prerequisites: Complete the Setup and Installation guide. You’ll place both apps on the same Domo page, and the
app-broadcasting feature switch must be enabled on your instance.Step 1: Scaffold both apps
Create two separate app projects:
Step 2: Configure the Selector App manifest
Open
selector-app/manifest.json and add the channels and datasetsMapping properties:
selection:changed uses the namespace:event convention: the namespace groups related channels; the event describes what happened.
Step 3: Build the Selector App component
Replace
selector-app/src/App.tsx:
Step 4: Configure the Detail App manifest
Open
detail-app/manifest.json:
Note: In production, an app receives a channel only if that channel is listed under
subscribes. Declaring selection:changed here is what wires the Detail App up to receive it.Step 5: Build the Detail App component
Replace
detail-app/src/App.tsx:
onBroadcast returns an unsubscribe function — call it in the effect cleanup so the subscription is removed when the component unmounts.
Step 6: Publish and test
Publish both apps and place them on the same App Studio page:
Pattern: Sync current state on mount
The bus keeps no history, so if the Detail App mounts after a row was already selected, it starts empty until the next click. To catch up, have the Detail App request the current selection when it mounts, and have the Selector App answer by republishing. Add a request channel to both manifests —
subscribes in the Selector, publishes in the Detail:
Pattern: Filtering by source
If a page has multiple Selector Apps and you only want to listen to one, use
domo.onBroadcastFrom():
sourceAppId on any message that app sends — it identifies a specific card instance on the page, so two copies of the same app have different IDs. Like onBroadcast, this returns an unsubscribe function.
Note: A visual broadcasting inspector for viewing live channel traffic and instance IDs is on the roadmap. Until then, log
sourceAppId during development to find an instance’s ID.Pattern: Multi-channel coordination
Real apps often use several channels. Here’s a Selector App that publishes both selection and hover events:
Pattern: One-time initialization
Use
domo.onBroadcastOnce() when an app only needs a message once — for example, an initial configuration from a coordinator app. It unsubscribes automatically after the first delivery:
Error handling
domo.broadcast() returns immediately and never throws. If the host rejects a message — a reserved domo: channel, a payload over 64 KB, more than 100 messages per second, or the feature switch being off — it notifies only the sending app, and the SDK writes a warning to the browser console:
Summary
Next steps
- App Broadcasting Guide — Architecture, limits, and lifecycle
- The Manifest File — Full channel declaration reference
- domo.js SDK Reference — Complete API documentation