Overflow Tap 1.0.0: switch Overflow Tap destinations from keywords in ProPresenter slide notes #47
Open
michael
wants to merge 2 commits from
claude/overflow-tap-module into main
pull from: claude/overflow-tap-module
merge into: :main
:main
:claude/vista-cues-picker
:claude/vista-cues
:claude/overflow-tap-module
:claude/layouts-menu-not-shown
:claude/timers-ltc-spawn-error
:claude/shell-tar-exec-bits
:claude/resi-cues-startup-pause
:claude/pco-multi-service-types
:claude/proddash-alerts-feature-67694f
:claude/send-message-module-refactor-9af19a
:claude/update-error-message
:claude/prodcom-filter-button-visibility-8a1d2d
:claude/spl-prebuilt-helper
:claude/timers-prebuilt-helper
:claude/release-builds
:claude/unbundled-shell
:claude/module-helper-rules
:claude/pco-song-key
:claude/timers-video-countdown
:claude/spl-build-retry
:claude/timers-build-retry
:claude/shell-keep-executables
:claude/shell-module-update-reload
:claude/timers-capture-install
:claude/pco-ableset-progress
:claude/proddash-ableset-module-6c2556
:claude/timers-second-phase
:claude/pco-teams-tile
:claude/resi-stage-cues
:claude/service-times-module
:claude/band-lineup-docs-tidy
:claude/band-lineup-display-1-3-10
:claude/spl-devices-without-binary
:claude/pco-message-match
:claude/grid-size
:claude/band-lineup-module
:claude/layout-audit
:claude/update-safety
:claude/module-rules
:claude/themes
:claude/admin-pin-trim
:claude/tile-chrome
:claude/readme-slack-module
:claude/slack-send-target
:claude/propresenter-now
:claude/gitea-is-home
:claude/admin-pin
:claude/shell-1-5-0
:claude/self-hosted-forge
:claude/no-campus-defaults
:claude/proddash-app-tweaks
:claude/slack-module
:claude/dashboard-round-2026-09
:claude/proddash-menubar-launcher-6eb34e
:claude/pco-plan-module-f711b9
:claude/prodcom-orientation-channels-icon-bcf897
:claude/prodash-propresenter-timers-cea871
:claude/proddash-app-build-gnwq7y
:claude/timers-ltc-stage-display
:claude/propresenter-timers-module
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What it is
A new module,
modules/overflow-tap, that does what Overflow's "ProPresenter Integration" helper app does, inside ProdDash — speaking the same Overflow API the helper speaks — so the helper on AB-ProPresenter can be retired once this is configured there.GET /v1/status/slide) and the announcement layer (GET /v1/announcement/slide_index+/active), once a second each.givefires on "Give!" and "#give", not on "forgiveness").Following host:port · Overflow: booth@church.org, 4 keywords. The tile's own status line carries no email.The Overflow API, and where it came from
Overflow's public API documents only reads for Tap. The first cut of this PR guessed a write route; this version instead makes exactly the calls the helper app makes (Overflow ProPresenter Integration 1.2.3, bundle read 2026-10-11 with the user's approval), against the Dashboard's own backend at
server.overflow.co:POST /nonprofit-dashboard/authentication/login/jwt{ email, password }GET /nonprofit-dashboard/propresenter/nonprofits/{id}/keywords[{ keyword, destinationName, tapGroups: [{ id, tapGroupName }] }]POST …/nonprofits/{id}/keywords?syncNonprofit=true{ keywords }GET …/propresenter/nonprofits,POST …/nonprofits/{id}/selectAll of it is in one file,
overflow.js, with the provenance at the top. Session handling: the token is cached across re-inits for the same login (an admin saving config five times must not become five sign-ins — Overflow answers 429 "too many attempts"); a 401 signs in again once and retries; a refused sign-in is not retried within 20 s. Google sign-in has no password, so the account needs one set — the admin help says so, as Overflow's article does.Testing
node modules/overflow-tap/keywords.selftest.js— 8 cases pinning the matching rule.node tools/overflow-tap-mock.js— a ProPresenter cycling through keyworded slides on:1602(announcement layer included;--no-announcementsfor an older one) plus the Overflow Dashboard API on:24720: any email/password signs in;--fail-switchrefuses every switch,--expire=20makes sessions expire,--login=<email>:<password>accepts one login only. Run ProdDash withOVERFLOW_TAP_API_BASE=http://127.0.0.1:24720.connect + eventswhen both change in one tick), token expiry → sign-in again with switching uninterrupted, 500 → red tile + alertTap not switched: …on channel 1 + retries, wrong login → the reason on the tile and in the health line with three sign-in attempts in 45 s, and recovery once the mock is back./state), tile removed with a clean console, admin config change mid-run, page reload.Not yet exercised: a real Overflow account. That needs the Dashboard login entered on AB; the helper app there should stay until the module is seen switching.
Shell untouched. Requires ProdDash ≥ 1.11.0 (alerts). README and CLAUDE.md carry the module and the mock.
🤖 Generated with Claude Code
A new module that does what Overflow's "ProPresenter Integration" helper app does, inside ProdDash: the live slide's notes are read from ProPresenter (GET /v1/status/slide, twice a second) and when they carry one of the admin page's keywords, the chosen Overflow Tap groups are pointed at that keyword's destination. One tile: the keyword Tap is on (and since when), its destination and the groups moved, a chip saying whether the slide on screen carries a keyword, and the last four switches. A failed switch turns the tile red with the reason, retries three times, and can flash an alert channel. Admin config: ProPresenter endpoint + password; Overflow client ID + API key (x-client-id / x-api-key, the public API's two headers); Tap groups to switch (multiselect read from the account over /groups); keywords as text, one per line (`give = Give Online`, optionally `@ Lobby, Kids Wing`); match mode (whole word / anywhere / own line); alerts switch + channel. The one unverified piece: Overflow's public API documents only reads for Tap (OpenAPI checked 2026-10-07), while Overflow's helper uses the Dashboard's private API. The switch is sent as PATCH /api/v3/tap/groups/{id} with the new destinationId — the natural shape for this API — and every switch is confirmed by reading the group back, so a refusal shows on the tile instead of passing silently. overflow.js is the one place to change if Overflow names a different route. Also: tools/overflow-tap-mock.js (a ProPresenter whose slide notes carry keywords on :1602 plus the Overflow Tap API on :24720, --read-only to fail every switch), keywords.selftest.js (14 cases), README + CLAUDE.md entries. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>The first cut guessed a write route on Overflow's public API, which documents only reads for Tap. With the helper app's bundle in hand (Overflow ProPresenter Integration 1.2.3, read 2026-10-11) the module now makes exactly the calls the helper makes, against the Dashboard's own backend: POST /nonprofit-dashboard/authentication/login/jwt a Dashboard sign-in → JWT GET /nonprofit-dashboard/propresenter/nonprofits/{id}/keywords the Keyword Mappings POST …/nonprofits/{id}/keywords?syncNonprofit=true { keywords } = the switch So the keyword → destination → Tap groups mapping stays where Overflow keeps it (Dashboard › Integrations › ProPresenter › Keyword Mappings) and is read from there: on start, every five minutes, on the tile's refresh button, and from every trigger's answer. Admin config shrinks to the ProPresenter endpoint, the Overflow Dashboard login (plus a Nonprofit ID only for an @overflow.co staff login) and the alert switch; the API-key, Tap-groups, keyword-text and match-mode fields are gone. Behaviour follows the helper: both the presentation layer (/v1/status/slide) and the announcement layer (/v1/announcement/slide_index + /active) are watched; when a layer's set of matched keywords changes to a non-empty set it is sent; matching is per word, case-insensitive, punctuation around the word ignored. The session token is cached across re-inits for the same login so an admin saving config repeatedly cannot trip Overflow's "too many attempts"; a 401 signs in again once; a refused sign-in is not retried within 20 s. tools/overflow-tap-mock.js now plays the Dashboard API (any email/password signs in; --fail-switch, --expire=<s>, --login=<email>:<password>) and gives the mock ProPresenter an announcement layer (--no-announcements for an older one). Verified against it: sign-in, keyword load, triggers on both layers, token expiry → re-login, 500 → NOT SWITCHED + alert + retries, wrong login → the reason on the tile and in the health line, and recovery. keywords.selftest.js pins the matching rule (8 cases). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.