index ↓
launchers and overlays
the hub and the system overlay are webapps.
s1 - two slots
a slot names one installed bundle for a system role:
- launcher. the home screen. press the menu button 5 times to reach it.
- overlay. the ui drawn on top of every webapp: notification toasts, the call banner, the pairing pin, the disconnected banner, the voice indicator, and the volume indicator.
you set both from the companion app. an empty slot uses the built-in one.
s2 - what every webapp gets for free
overlays default on. a webapp that declares nothing gets all six.
turn one off in the manifest's overlays block when you draw it yourself. an omitted key stays on, so list
only what you take over.
{
"id": "…",
"name": "My App",
"version": "0.1.0",
"overlays": {
"volume": false,
"notifications": false
}
}
the six keys are notifications, call, pairing, connection,
voice, and volume. a key gates the drawn ui only; the events still reach your webapp.
s3 - build a launcher
bun create bridgething my-hub --launcher "role": "launcher" hides the bundle from client.webapp.list and makes it eligible for the
launcher slot.
{
"id": "…",
"name": "My Hub",
"version": "0.1.0",
"role": "launcher"
} everything a home screen needs is on the normal client:
// the daemon hides launcher-role bundles from this list
const list = await client.webapp.list();
const current = await client.webapp.current();
const icon = await client.webapp.icon({ id: info.id });
await client.webapp.activate({ id: info.id });
// redraw when a webapp is installed or removed
client.webapp.onWebappInstalled(reload);
client.webapp.onWebappUninstalled(reload); the built-in hub also handles bluetooth bonds and the pairing name, display brightness, system health, power, and ota progress.
s4 - build an overlay
bun create bridgething my-overlay --overlay {
"id": "…",
"name": "My Overlay",
"version": "0.1.0",
"overlay": "overlay.js"
}
while your bundle holds the overlay slot, the daemon injects overlay.js into every webapp's document as
it loads.
// the daemon prepends this before your bundle
window.__bridgethingOverlay = {
origin: 'http://127.0.0.1:8891',
surfaces: {
notifications: true,
call: true,
pairing: true,
connection: true,
voice: true,
volume: false, // this webapp draws its own volume indicator
},
}; honor surfaces. draw only what its keys allow, or the screen shows
that ui twice.
const cfg = window.__bridgethingOverlay;
if (!cfg || !location.origin.startsWith(cfg.origin)) return; // not a page the daemon served
if (window.__bridgethingOverlayMounted) return; // double injection is a no-op
window.__bridgethingOverlayMounted = true;
if (cfg.surfaces.volume) wireVolume(client);
if (cfg.surfaces.pairing) wirePairing(client); - origin guard. run only in a page the daemon served.
- mount guard. a second injection must do nothing.
- closed shadow root. it keeps your styles and the webapp's apart.
- escape-only, capture-phase keys. bind them only while something is showing.
overlay.js must be one self-contained file under 512 KiB.
s5 - assign it, and get back
install the bundle, then pick it in the companion app under home screen or overlay.
to get back to the built-in:
- clear the slot in the companion app.
- uninstall the bundle
- factory reset