For review · from White Oak Media

ProDeck Adopter's Guide

ProDeck is a production-booth hub I built for my church: one app that ties ProPresenter, Planning Center, the audio consoles, NFC "tap" discs, crew phones, and the livestream into dashboards for the booth, phones, and kiosk screens.

This guide is honest about what you'd be adopting. Part I is the evaluation — what it does, what it assumes, and what's tuned to my room. Part II is the adoption — everything your tech person needs to stand it up in your environment without me on the phone.

Source github.com/whiteoakmedia/prodeck (public) Version 0.9.66 Contact zach@whiteoakmedia.io
  1. 01What you'd actually be adopting
  2. 02Feature tour, with requirements
  3. 03The stack it assumes
  4. 04What's specific to my church
  5. 05Limitations, stated plainly
  6. 06Fit checklist & effort estimate
  7. 07Phase 0 — try it on a spare Mac
  8. 08Phase 1 — the booth install
  9. 09Phase 2 — your own cloud
  10. 10Phase 3 — the extras
  11. 11Ongoing care & staying current

Part I — Evaluate

01What you'd actually be adopting

Not a product. ProDeck is one church's custom tool: no vendor, no support contract, no license fee, and one maintainer (me), whose priority is my own Sunday. You'd be adopting a codebase — a well-documented one, but a codebase. The realistic ways to hold it:

What it costs to run: a Mac in the booth, and if you want the phone/remote features, a Cloudflare account (free tier is enough) plus a domain (~$10/yr). That's the entire bill.

02Feature tour, with requirements

Every feature is independent — adopt the rows you want, ignore the rest. CORE needs only the booth Mac + ProPresenter + Planning Center. + X names the extra dependency.

Booth

FeatureNeedsWhat it does
DashboardsCOREDrag-and-drop widget grids (rundown, now/next, slide grid, clocks, timers, readiness lights…), multiple named layouts, role templates. Same UI serves the booth screen, browsers, phones, kiosks.
Show flowCOREThe PCO rundown with computed wall-clock start times, per-song key/leader/mic chips, live-item tracking that follows what's actually on the screens.
Service tracking & reportsCOREPlanned vs. actual timing per item, bucketed per service time; rehearsals kept out of Sunday stats; saved reports.
Clear dockCOREOne-tap ProPresenter layer clears (slide/media/props/messages/…) pinned to every page.
SPL + RTA metering+ audio inputCalibrated house SPL, RTA, history graphs, per-service loudness records. Built for Dante Virtual Soundcard; any CoreAudio input works.
Console mirror+ a supported deskChannel names/mutes/faders on dashboards, mic names pushed to the desk weekly. Allen & Heath Avantis, dLive and SQ (MIDI over TCP) and Behringer X32 / Midas M32 (OSC). Only the Avantis has been run against real hardware; the rest are built from the published protocols. Any other desk means new code.
Song-key MIDI send+ MIDI routeSends the live song's key as a MIDI program change (I target Waves LV1 scenes). Generic PC/CC sender — usable against anything that takes MIDI.
Stage feed preview+ NDIAny NDI source as a dashboard tile (LAN only, by design).

Crew & cloud

Crew phone app+ cloudInstallable web app: dashboards, plan, chat, push pages. Poster-QR signup with booth approval; names self-heal against PCO.
Paging & call times+ cloudPage a person or team (phones buzz), scheduled call-time pages per PCO team, booth↔stage messages, confidence banner.
Check-in+ cloudCrew auto-marked arrived when their phone joins your network (or by geofence); arrival board against call times.
Booth-off fallback+ cloudWhen the booth Mac is off, your domain still serves a read-only plan + working chat + signup from Cloudflare's edge.
Kiosk mode+ cloudURL-parameter kiosks: office screens, a "what's next" switcher dashboard for a touchscreen at the video position.

Lobby & stream

TapLink NFC discs+ cloud + NFC tagsThe flagship trick: NFC discs in the lobby all open one link whose destination follows the service — a slide with tap: give in its ProPresenter notes retargets every disc to your giving page the moment it goes live. Manual override, auto-release, tap analytics.
Lobby TV auto-announcementsCOREDrives a ProPresenter announcement playlist for lobby screens.
Live viewer count+ GA4Realtime "watching now" from the Google Analytics tag on your stream's watch page (matches GA4's own realtime screen). Works with Church Online Platform or any watch page you can tag.
Stream Deck+ CompanionTap-disc keys with live state, dB and check-in readouts, page navigation, via Bitfocus Companion.

03The stack it assumes

ComponentRequirement
A Mac in the boothREQUIRED Intel or Apple Silicon (macOS 10.15+), always on, always awake. This is the server for everything. There is no Windows or Linux build.
ProPresenter 7REQUIRED with the network API enabled (Preferences → Network). ProDeck reads slides/playlists/notes and triggers over it.
Planning Center ServicesREQUIRED — plans, teams, and scheduling are the backbone. You press Connect and approve ProDeck on Planning Center's own page — it asks for Services and People, nothing else. (A Personal Access Token still works if you prefer one.)
Cloudflare + a domainOPTIONAL — only for the crew/cloud/tap features. Free plan suffices; the domain is the only recurring cost.
Dante / audio interfaceOPTIONAL — SPL features take any input the Mac can hear.
A supported sound consoleOPTIONAL — A&H Avantis / dLive / SQ, or Behringer X32 / Midas M32. Anything else is unsupported.
OBS StudioOPTIONAL — scene, stream/record state and dropped frames, via OBS's built-in WebSocket server.
NDI source, Stream Deck, NFC tags (NTAG213+), GA4 on your watch pageOPTIONAL — one feature each.

04What's specific to my church

The honest answer to "how personalized is this?" — in three tiers.

Tier 1 — just settings (change in the app, no code)

ProPresenter host, PCO credentials, all passwords and tokens, GA4 property/key, church coordinates, SPL calibration, MIDI ports and channels, Avantis host, audio channel routing, mic-position templates, checklists, call-time schedules, tap keyword→URL mappings, dashboard layouts. None of my values ship in the repo — a fresh install starts blank.

Tier 2 — your environment (nothing to edit in code)

Everything site-specific is either a Setting or a gitignored local file, so your fork never carries your values in source:

WhatWhere it lives
Your public domain (crew phones off-site, the edge fallback, the permanent /join QR)Settings → Browser Access → Public URL. The edge push URL is derived from it.
Cloudflare Worker routes for your zonecrew-edge/wrangler.local.jsonc and taplink-edge/wrangler.local.jsonc (gitignored; copy the committed wrangler.jsonc and fill in your route)
Bundle identifier, signing identity, updater endpoint + public keysrc-tauri/tauri.local.conf.json (gitignored overlay; scripts/setup.sh creates it). Leave the placeholder updater block in tauri.conf.json alone — if you never publish updates the check simply fails quietly in Settings.

Tier 3 — shaped by my room (works for you, but review it)

05Limitations, stated plainly

06Fit checklist & effort estimate

You're a good fit if…

Think twice if…

Realistic effort (for a comfortable tech volunteer)

MilestoneTime
Phase 0 — running on a spare Mac against Pro + PCOan afternoon
Phase 1 — permanent booth install (signing, watchdog)half a day
Phase 2 — your domain, workers, tunnel, crew phonesa day, mostly waiting on DNS
Phase 3 — discs, deck, kiosks, GA4 (each independent)1–3 hours each

Part II — Adopt

07Phase 0 — try it on a spare Mac

Zero commitment: dev mode on any Mac (Intel or Apple Silicon) on your church network. No signing, no cloud, no install.

# prerequisites (one-time): Xcode command-line tools, Rust, Node 20+
xcode-select --install
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
brew install node   # or nodejs.org installer

# get the code (after I've added you to the repo)
git clone https://github.com/whiteoakmedia/prodeck.git
cd prodeck
bash scripts/setup.sh   # prereqs + config + dev mode, all guided

First run opens a setup wizard. Point it at ProPresenter (the ProPresenter machine's address (Find discovers it, or read the host and port from ProPresenter → Preferences → Network)) and press Connect for Planning Center, which signs you in on planningcenteronline.com itself — no password or token is typed into ProDeck. That's enough to evaluate everything tagged CORE in §2 — dashboards, show flow, slide grid, tracking, clear dock — plus SPL if you pick an audio input.

Evaluate against a real week

Load next Sunday's actual plan and leave a dashboard up through a midweek rehearsal. The value shows up in use, not in a demo click-through.

08Phase 1 — the booth install

Makes it permanent: a signed build that survives crashes and reboots unattended.

1 · Create your signing identity (once)

Keychain Access → Certificate Assistant → Create a Certificate: name it (e.g. YourChurch ProDeck), identity type Self-Signed Root, certificate type Code Signing. macOS pins microphone/screen permissions to this identity — keep using the same one forever, and never re-sign with hardened runtime (the install script refuses it for you).

2 · Create your updater keypair (once, optional)

npm run tauri signer generate -- -w ~/.prodeck/updater.key

Put the printed public key and your fork's release feed into the gitignored overlay src-tauri/tauri.local.conf.json (plugins.updater.pubkey / endpoints, plus bundle.createUpdaterArtifacts: true) — not into the committed tauri.conf.json. If you never publish updates, skip this step entirely. Guard the private key like a password: whoever holds it can ship code to your booth.

3 · Build, sign, install

TAURI_SIGNING_PRIVATE_KEY="$(cat ~/.prodeck/updater.key)" \
  npm run tauri -- build --bundles app --config src-tauri/tauri.local.conf.json
codesign --force --deep --sign "YourChurch ProDeck" \
  src-tauri/target/release/bundle/macos/ProDeck.app   # no hardened runtime
bash scripts/install-local.sh   # atomic swap into /Applications + watchdog handoff

Prefer a double-click installer? bash scripts/build-dmg.sh produces a drag-to-Applications ProDeck.dmg — hand it to anyone, no terminal needed to install (only to build). For an always-on booth, the script path below adds crash-relaunch and keep-alive that a plain drag-install does not.

scripts/install-local.sh refuses a bundle that isn't signed with your identity (or one signed with hardened runtime), and installs the watchdog LaunchAgent template from step 4 for you.

4 · The LaunchAgents

Ready-made templates live in deploy/launchagents/ — scripts/setup.sh --install installs and loads them for you. For reference:

PlistPurpose · ProgramArguments
com.prodeck.watchdog.plistRelaunch on crash · /Applications/ProDeck.app/Contents/MacOS/prodeck, RunAtLoad true, KeepAlive.SuccessfulExit false, ThrottleInterval 10
com.prodeck.caffeinate.plistNever sleep · /usr/bin/caffeinate -s, KeepAlive true
com.prodeck.cloudflared.plistPhase 2 only — the tunnel (§9). Not in the repo; you create it when you set up the tunnel.

Finish by enabling Browser Access in Settings (pick your admin + member passwords) and giving the booth Mac a DHCP reservation — do the ProPresenter Mac too, and skip the single most recurring failure I ever had.

09Phase 2 — your own cloud

Unlocks: crew phones anywhere, booth-off fallback, tap discs, kiosks beyond the LAN. Needs a Cloudflare account (free) and a domain on it.

  1. Domain onto Cloudflare. Buy or transfer any domain; add it as a zone.
  2. Point ProDeck at your domain — Settings → Browser Access → Public URL, and your zone's route in crew-edge/wrangler.local.jsonc (§4, Tier 2).
  3. Deploy the two workers. In crew-edge/ and taplink-edge/: npx wrangler login then npx wrangler deploy. Set each worker's secrets with npx wrangler secret put <NAME> — the names are listed at the top of each worker's src/index.ts (admin token, PCO pair for the edge fallback, tap tokens).
  4. Tunnel the booth. brew install cloudflared, then cloudflared tunnel login, cloudflared tunnel create booth, and a config at ~/.cloudflared/config.yml routing your hostname → http://localhost:8088. Add the DNS route (cloudflared tunnel route dns booth yourdomain.com) and wrap it in the com.prodeck.cloudflared LaunchAgent. Tunnel only the gateway port — never video.
  5. Wire the booth to the edge: Settings → paste the edge admin token you chose in step 3. From then on install-local.sh keeps the edge's fallback copy in sync on every install.
  6. Verify booth-off mode: quit ProDeck (watchdog off for a minute) and load your domain from a phone on cellular — you should get the read-only plan + chat. Restart, and it's live again.

10Phase 3 — the extras

FeatureSetup
Tap discsBuy NTAG213+ stickers/discs, write each with your tap URL (any NFC-writer phone app), map keywords → URLs in the TapLink widget's editor, then put tap: keyword in ProPresenter slide notes. Discs are dumb pointers — all logic is server-side, so you can add discs forever without rewriting them.
Stream DeckInstall Bitfocus Companion on the booth Mac, add an HTTP connection pointed at localhost:8088 with your admin password as the prodeck_token variable. The gateway's deck endpoints (deck-state, tap actions, readouts) are documented in src-tauri/src/web.rs.
KiosksAny screen with a browser: https://yourdomain/?kiosk=<dashboard name>&token=<member password>. Windows auto-boot recipe is in OFFICE_KIOSK.md in the repo.
Live viewersMake a GA4 property for your watch page, put its tag on the page (Church Online has a built-in GA4 integration), create a Google Cloud service account with the Analytics Data API enabled, grant it Viewer on the property, drop its JSON key on the booth Mac, fill in Settings → Live Viewers. Full recipe with the exact error messages you'll hit is in the repo's ga4.rs header comments.
SPL calibrationPlay pink noise, read a real SPL meter at FOH, and adjust the calibration offset in Settings until they agree. Mine is meaningless in your room.

11Ongoing care & staying current

Where I land on it

If the tap discs, crew phones, or one-glance dashboards solve a real problem for your team, the adoption cost is a few honest days and a codebase to own. If they don't, skip it without guilt — everything underneath (Pro, PCO, your consoles, your stream) already works without it. Questions to zach@whiteoakmedia.io.

↑ Back to contents