ProdDash now has a version (package.json, 1.1.0) and modules declare the
shell versions they need ("proddash": ">=1.1.0" in the manifest). A module
whose requirement this shell doesn't meet is listed in the admin page but
never loaded, and cannot be installed from the catalog.
Modules come from two places: bundled with the checkout (modules/) and
installed from the admin page into the data directory (<data dir>/modules/).
Same id in both → the newer version runs; a downloaded copy the bundled one
has overtaken is removed. The admin page's new "Available modules" section
lists modules in the ProdDash repo that aren't installed here — one small
tar.gz of the branch is fetched (at most every few minutes, only while the
admin page is open or for the periodic update check) and read with a
dependency-free tar reader (ustar, GNU long names, pax headers; the pax
global comment carries the commit sha). Install downloads the module folder
into the data directory and mounts it immediately; a module card offers
"Update to vX" when the repo has a newer version. Uninstall removes an
installed module's files; a bundled module is hidden instead (its folder
belongs to the app) and can be restored from Available modules without a
download. Settings are kept across uninstall/reinstall.
Shell updates: the server compares the repo's package.json version and
commit sha with its own (git rev-parse when the app folder is a checkout),
shows a banner in the admin page, and "Update now" brings the app folder up
to date — git pull --ff-only for a checkout that is on the repo branch with
no local changes (file modes ignored), otherwise the archive is unpacked over
the folder (runtime state and .git untouched). The server then exits with
code 75 and starts its own replacement unless PRODDASH_LAUNCHER is set; the
replacement waits for the port to free up (EADDRINUSE retry). The page polls
until the new version answers. PRODDASH_REPO (owner/repo#branch),
PRODDASH_ARCHIVE_BASE and PRODDASH_NO_REMOTE_CHECK configure/disable it.
Docs: MODULE-GUIDE gets the rules every module follows (all settings in the
admin page, dependencies shipped inside the module, everything runs inside
the module's server entry — no helper programs, declare the ProdDash
requirement and bump the version), the proddash/version manifest fields and
the new installation story; README gets "Installing modules and updating";
CLAUDE.md summarises the rules.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
58 lines
3.4 KiB
Markdown
58 lines
3.4 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/`. 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()`. 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).
|
|
- 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).
|
|
|
|
## 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`
|
|
(default `http://10.3.11.152:24480`). 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.
|