Files
Waters ChurchandClaude Fable 5.1 5ca0a672fa Shell 1.11.0: alerts — a module flashes every dashboard listening on one of six channels
A module that sees something a tech must act on now (a timer overrun, a meter
past its limit, timecode gone) raises an alert on a channel, 1–6, and every
dashboard listening to that channel flashes: the menu bar — brought out for
the duration if it was hidden — and a frame round the screen alternate between
the level's two colours, with the alert's text bold across the bar. Low fades
slowly, medium faster, critical snaps with no fade and floods the board behind
the tiles too, in a muted cut that shows faintly through the tile panels
without costing their content any contrast.

Server: the hub. One alert per channel (a new one replaces the last), timed
out server-side (1–600 s, 15 by default, 0 = held until cleared), broadcast
over the shell stream as `alert` / `alert-clear`; GET /api/alerts for a
dashboard that opens or reconnects mid-alert; POST /api/alerts and
DELETE /api/alerts/<n>, open like a layout save. Modules raise from their
server entry with shell.alert() / shell.clearAlert() or from a tile with
moduleApi.alert() / moduleApi.clearAlert(); a module's alerts end when it
stops. Colours live as alerts.colors in the data directory's proddash.json.

Dashboard: the Layouts menu gains a folded Alerts row with six numbered
toggles; the channel list saves with the layout, local and named (the server
keeps it in a saved layout). Admin: a folded Alerts section with two colour
pickers per level, a swatch running each level's cadence, and a Test row.

Docs: docs/ALERTS.md (the feature), a "Raising alerts" section in the module
guide, README. Tools: tools/alert.js raises/clears/lists from the command
line; tools/alerts.test.js drives it all end to end.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-05 16:05:12 -04:00

6.9 KiB

ProdDash Alerts

A module that sees something a tech must act on now — a timer overrun, a meter past its limit, timecode gone — raises an alert, and every dashboard listening to its channel flashes until it is over. This page is the whole feature: what an operator sees and sets, and what a module does to raise one. The module-side contract also lives in the Module Guide, which is the authority on how modules are written.

What an alert looks like

On a dashboard that listens to the alert's channel:

  • The menu bar flashes between two colours, with the alert's text in bold across its middle (and a small boxed number saying which channel it came on). If the bar was hidden — by its notch, or because the screen is in fullscreen — it comes out for the alert and goes back when it ends.
  • A frame round the whole screen flashes with it, so a fullscreen wall where the bar is the only chrome still carries the flash to its edges.
  • For low and medium, that is all: the tiles and the board they sit on are left alone. A critical alert floods the board behind the tiles as well — in a muted cut of its two colours, mixed well toward the page background and showing faintly through the tiles' own panels — so the flash reaches the middle of a screen the tiles cover entirely, while everything written on a tile keeps its contrast. A module's content is never recoloured.

The level sets the cadence. The two colours each level flashes between are the admin's choice (below).

Level Cadence For
Low a slow fade between the two colours, about three seconds a cycle; bar and frame only something to know about
Medium a faster fade, about one second a cycle; bar and frame only something to deal with soon
Critical no fade — the colours snap, twice a second; bar, frame and the board behind the tiles something to deal with now

When several alerts a dashboard listens to are on at once, the bar shows the most severe (the newest among equals) and a +1 says how many more there are.

Channels

There are six channels, numbered 1 to 6, and nothing else: a channel carries no meaning of its own. A booth gives them meaning — "1 is the stage, 2 is video, 3 is the lobby" — by pointing modules at them (a module that raises alerts makes its channel an admin setting) and by choosing which channels each dashboard listens to.

Choosing channels: on the dashboard, open the Layouts menu (the grid icon) and the Alerts row — it says which channels this screen listens to and opens to six numbered buttons that toggle them. The choice is part of the arrangement, like the grid size and auto-hide: it saves with this browser's layout and with a named layout on the server, so a booth that loads its "Stage" layout gets the stage's channels with it. A fresh dashboard listens to nothing.

One alert per channel

A channel shows one alert at a time. A new alert on a channel replaces whatever was on it, whoever raised it; clearing a channel ends whatever is on it. Two modules pointed at one channel will talk over each other — give them channels of their own.

An alert ends when its duration runs out (1 to 600 seconds; 15 when the module gives none), or when the module that raised it clears it early, or when that module stops (a disable, an uninstall, a config save that re-inits it): a module's alerts never outlive it. A module may hold an alert until cleared (duration 0) for a condition it will notice ending — timecode lost, a feed down — and clear it when the condition does.

Admin → Alerts

The admin page's Alerts section (folded by default, near the bottom) holds two colour pickers per level — the two colours that level flashes between — with a swatch beside each row running that level's cadence, so a pair can be judged before it is tried. A change saves when the picker closes and reaches every open dashboard at once. The row below sends a test alert of any level on any channel: eight seconds of whatever the dashboards listening to that channel will see.

The colours are kept as alerts.colors in the data directory's proddash.json (see the README's Where settings are kept); they hold across restarts and updates. The defaults are a blue pair for low, amber for medium and red against near-black for critical.

For module authors

Raise from the server entry, which is where a condition is usually noticed — shell.alert({ channel, level, text, duration }) and shell.clearAlert(channel) on the shell object init(), routes() and tiles() receive — or from a tile with moduleApi.alert(...) and moduleApi.clearAlert(...), which go through the server. The fields, what each is for, and the rules that keep alerts worth looking at (raise on the transition, make it a setting, it is not a status) are in the Module Guide.

The HTTP API

Everything above rides on three public routes and two admin ones. They are open to anything that can reach ProdDash, like a module's own routes: an alert is a flash on screens in this building and nothing more.

Route Does
GET /api/alerts { channels: 6, levels, colors: { low: [a, b], … }, active: [ … ] } — what is flashing and the colours. Dashboards read it on load and whenever their stream reconnects.
POST /api/alerts { channel, level, text, duration?, source? } as application/json. Answers 200 { ok, alert } or 400 { error } saying what was wrong. source is the module id (anything else is recorded as api).
DELETE /api/alerts/<channel> Ends the alert on that channel. { ok, cleared } — cleared is false when nothing was on it.
POST /api/admin/alerts { colors: { low: [a, b], medium: [a, b], critical: [a, b] } } — a missing or malformed colour takes its default. Behind the admin PIN.
POST /api/admin/alerts/test { level, channel } — an eight-second test alert. Behind the admin PIN.

Open dashboards learn of changes over the shell stream (/api/events): alert carries an alert as raised ({ id, channel, level, text, source, startedAt, duration, endsAt, remainingMs } — a browser counts down from remainingMs, so the clocks need not agree), alert-clear carries { channel, id } when one ends, and alerts-config carries { colors } when the admin changes them.

Trying it

With ProdDash running, from the repo:

node tools/alert.js -c 1 -l critical "LTC lost"

raises a critical alert on channel 1 for the default 15 seconds; -d 0 holds it, node tools/alert.js -c 1 --clear ends it, --list shows what is on. Open a dashboard, choose channel 1 in its Layouts menu → Alerts, and watch; a second browser listening to channel 2 should stay quiet. The admin page's Test buttons do the same from the browser. node tools/alerts.test.js runs the server's side of all this end to end.