The macOS app and the Windows bundle shipped every module in the repo, on
by default, and a shell update silently added whatever new module had
landed on main — Band Lineup appeared on AB that way. A module was also
only as fresh as the last shell update. Now a packaged install (no .git —
the same test the updater uses to choose the archive over git pull)
carries no modules at all: every one arrives from the admin page's catalog
into the data directory, and the shell's own update never writes modules/.
A git checkout keeps running the modules in its tree.
Existing installs move over by themselves: at the first start, the bundled
modules that are switched on are copied into the data directory as
installed copies (a compiled helper keeps its mode), an uninstalled one is
dropped, and the app folder's modules/ is removed. Settings are keyed by
module id, so nothing changes for the operator.
Around it: the dashboard's empty state says "No modules yet — open Admin"
when the registry is empty; the admin page says "Nothing installed yet",
puts a checkbox on every compatible catalog entry and an Install selected
button (POST /api/admin/modules/install {ids}) that fetches them in one go.
The Mac build stops copying modules/ and no longer compiles or signs Swift
helpers — those ship prebuilt inside a module, per the guide.
tools/unbundled.test.js drives a packaged copy of the shell through the
move, an archive update that must not bring modules back, and a multi-install.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
77 lines
4.9 KiB
Markdown
77 lines
4.9 KiB
Markdown
# ProdDash
|
|
|
|
Modular production dashboard web app for Waters Church, developed in this repo.
|
|
The app lives at the repo root and is built: zero-dependency Node server
|
|
(`server.js`, Node 18+), dashboard shell client in `public/`, admin page at
|
|
`/admin`, modules in `modules/` (the repo's copies — a packaged install ships
|
|
none and installs them from the admin page's catalog), and a native macOS menu-bar launcher in
|
|
`launcher/macos/` (Swift, no dependencies — the shipped macOS app: it carries
|
|
the server and its own Node runtime, supervises them, and owns the macOS
|
|
permissions modules declare; see its README). Runtime state (module
|
|
config, named layouts) is written to a per-machine data directory outside the
|
|
checkout (`PRODDASH_DATA_DIR` overrides; see README "Where settings are
|
|
kept") — never add code that writes runtime state into the repo folder.
|
|
[SPEC.md](SPEC.md) was the authority for the initial build;
|
|
[README.md](README.md) has run/configure/use instructions.
|
|
|
|
## Building a new module — read docs/MODULE-GUIDE.md first
|
|
|
|
**[docs/MODULE-GUIDE.md](docs/MODULE-GUIDE.md) is the authority on the module
|
|
contract** (manifest, client factory + moduleApi, optional server entry,
|
|
title-bar controls). The rules that matter most:
|
|
|
|
- A module is one self-contained folder in `modules/` — **never modify the
|
|
shell** (`server.js`, `public/`) to add one. Installation = the admin page's
|
|
Available modules (downloads from the repo into the data directory), or
|
|
drop the folder and restart; configure in `/admin`.
|
|
- **All settings in the admin page** (`configSchema` / `instanceSchema`) —
|
|
never a separate setup page, hand-edited file or env var. **Dependencies
|
|
ship inside the module folder** (zero deps is the norm). **Everything the
|
|
module does runs inside its server entry** — no helper scripts, companion
|
|
programs or daemons the operator starts by hand; a listener or decoder is
|
|
started in `init()` and stopped in `stop()`. **A native helper ships
|
|
prebuilt inside the module folder for Apple silicon macOS and 64-bit
|
|
Windows** (`bin/<name>-macos-arm64`, `bin/<name>-win-x64.exe`, source and
|
|
build script under `native/`); nothing is ever compiled on the machine
|
|
running ProdDash, and a missing binary means the feature reports itself
|
|
off, not a broken module. Declare `"proddash": ">=x.y.z"`
|
|
and bump the module's `version` on every change.
|
|
- Browsers never call upstream services directly; the module's server routes
|
|
proxy everything (no CORS, secrets stay server-side).
|
|
- **Keep the interface clean** (guide rules 5-11): no `help` and no label
|
|
over three words in a tile's gear; server-side settings in `configSchema`
|
|
only; a tile setting changes that tile alone; hide-toggles ungrouped when
|
|
there are four or fewer, in a folded **Show** group when there are five or
|
|
more; title-bar controls are icons with tooltips, never labels, and never
|
|
repeat something the gear already offers.
|
|
- Style with the shell's CSS variables only, scoped under
|
|
`[data-module="<id>"]`; survive upstream loss (reconnect + `setStatus`).
|
|
- Verify against the guide's testing section and resilience checklist. Mocks
|
|
for the existing upstreams: `node tools/prodcom-mock.js` (ProdCom) and
|
|
`node band-lineup-display/tmp/pp-mock.js 1599` (ProPresenter).
|
|
`node tools/slack-mock.js 24716` (Slack; run ProdDash with `SLACK_API_BASE=http://127.0.0.1:24716/api`).
|
|
`node tools/pco-band-mock.js 24710` (Planning Center for Band Lineup; run ProdDash with `BAND_LINEUP_API_BASE=http://127.0.0.1:24710`).
|
|
`node tools/ableset-mock.js 39071` (AbleSet over OSC/UDP; point the AbleSet module at `127.0.0.1:39071`; `--stopped`, `--no-live`, `--speed 4`).
|
|
|
|
## Reference code (read-only forks — don't develop these here)
|
|
|
|
- `prodcom-listener/` — live ProdCom transcript web app. Zero-dependency Node
|
|
`server.js` that serves `public/` and proxies `/prodcom/*` (including the SSE
|
|
transcript stream) to the ProdCom API at `config.json → prodcomUrl`
|
|
(set per site; each campus runs its own). Good reference for: SSE handling,
|
|
reconnect logic, channel colors/filtering, PWA install.
|
|
- `band-lineup-display/` — backstage Electron app (stage lineup photos with
|
|
mic/pack labels) plus ProPresenter Now/Next:
|
|
- `band-lineup-display/propresenter-core/` — shared ProPresenter 7/20 client,
|
|
no deps, no Electron. All ProPresenter quirks live here (PP20 runtime route
|
|
discovery, arrangement-expanded slide totals, uuid-then-name live-item
|
|
matching). Reuse this rather than re-implementing ProPresenter access.
|
|
- `band-lineup-display/propresenter-app/` — standalone Now/Next web display.
|
|
- `band-lineup-display/tmp/pp-mock.js` — mock ProPresenter API for testing
|
|
without the real thing: `node tmp/pp-mock.js 1599`, then point at
|
|
`127.0.0.1:1599`.
|
|
|
|
Upstream sources: ProdCom Listener lives at
|
|
`github.com/michaelmcgary2008/prodcom-listener`; BandLineupDisplay exists only
|
|
on the production machine. These folders are snapshots, not submodules.
|