Stage Now / Next
The ProPresenter Now / Next display, as its own program — the same feature that lives in the Band Lineup app's right-hand column, but on its own so it can run on studio machines, hallway TVs, green-room tablets, anywhere in the building.
Both programs share one engine: ../propresenter-core.
Fix a ProPresenter quirk there and both get the fix.
The easiest way: let the Band Lineup app host it
If the backstage machine already runs Band Lineup, you don't need to start anything here. Open the app, and in the People panel find Studio Displays → Turn On.
It then lists the addresses to use, best first, each with a Copy button. Open one on any screen in the building and bookmark it. Nothing to install on those screens.
Because the app hands the display its own ProPresenter connection, there is exactly one connection to ProPresenter no matter how many screens are watching, and the studios always show precisely what the backstage screen shows. The connection is still set up in one place — the app's ProPresenter section — and the studio screens' own settings are locked, with a note saying so.
The displays are live whenever Band Lineup is open. Close the app and every screen says Display offline and names the backstage computer, rather than quietly showing a frozen lineup. They come back on their own when the app reopens — no reloading needed.
The bookmark that keeps working
The first address in the list is http://nownext.local:7654. The app publishes that name
itself over mDNS, so the bookmark survives the backstage machine getting a new IP from DHCP.
It resolves on Macs, iPads and Windows 10/11.
Do not bookmark the computer's own name (http://backstage-pc.local:7654) — Windows can
resolve mDNS names but never publishes its own, so Macs and iPads get nothing back.
If nownext.local doesn't work on a particular screen (some managed networks and separate
VLANs block mDNS), use one of the numeric addresses below it. Once any screen has loaded
the page from an address, that address is relabelled Confirmed working and moves to the
top — so after the first studio connects, the app knows the right answer for your building.
For a permanently fixed address, ask IT for a DHCP reservation on the backstage machine, and
optionally a DNS name pointing at it. One caveat if you go the DNS route: the zone must not
end in .local, or Apple devices will route the lookup to mDNS and it will fail.
If a studio screen can't load the page (Windows)
Almost always Windows Defender Firewall. Two things make this confusing:
- The prompt appears when the app starts serving, not when a studio first connects — so
the backstage machine looks perfectly fine on
localhostwhile every other screen times out. - If whoever answered the prompt wasn't a local admin, Windows creates block rules no matter which button they pressed, and it never asks again.
The installer adds the allow rules for you, so a normal install is fine. If you're running an unpacked build or the rules got lost, an admin can restore them:
netsh advfirewall firewall add rule name="Band Lineup Display (TCP)" dir=in action=allow program="C:\Program Files\Band Lineup\Band Lineup.exe" enable=yes profile=domain,private protocol=TCP
The app helps you spot this: if hosting is on and no screen has ever connected, the Studio Displays status line says so and names the port to allow.
Other things that break a working setup: the backstage PC sleeping (turn off sleep on a machine that hosts displays), and Windows flipping the network profile to Public — the allow rules above only cover Domain and Private.
Keep the studio screens awake
The page asks the browser for a screen wake lock, but browsers only grant that on a secure (HTTPS) origin, and this is served over plain HTTP on the LAN — so the request is always refused. Turn off screen sleep in the OS settings on any machine or tablet you leave running as a dedicated display; the web page cannot do it for you.
Security: what's protected, and what isn't
Be clear-eyed about this one, because the honest answer is unusual.
Viewing is deliberately open. Anyone who can reach the port can watch the page. There is no password, and adding one was considered and rejected: a wall TV has to come back by itself after a power cut with nobody standing there, and a login prompt, a key in the URL, or a certificate warning all break exactly that. A key in the URL would also live forever in every bookmark and in the address list volunteers copy into group chats.
More importantly, gating this page would not raise the bar much. ProPresenter's own network API on the same LAN has no authentication at all, and unlike this page it is not read-only. Anyone who can reach this display can already read the same service order straight from ProPresenter — and put whatever they like on the main screen. Network placement is the control that actually covers both.
What is protected
- Nothing can be changed over the network while the Band Lineup app is hosting. The
connection routes return
409, so a browser on the LAN cannot retarget or disconnect the display. Standalone additionally requiresapplication/json, a same-origin request, and a recognisedHost— which blocks the JavaScript-free form CSRF and DNS-rebinding writes that are otherwise possible against a local HTTP server. - Hidden items stay hidden. Anything flagged hidden in ProPresenter — cut songs, contingency cues, staff-only slides — has its name stripped before it leaves the machine, not merely skipped when drawing the page.
- The playlist library is not exposed.
/api/playlistsis refused while the app is hosting. - Connection limits. Concurrent viewers are capped (32 total, 6 per device) so nobody can pile up connections inside the app, and a screen that stops reading is dropped rather than buffered forever. Established screens are never dropped to make room for a new one.
- The mDNS name can't be stolen with one packet. A claim on
nownext.localis verified by probing before this host stands aside, and it reclaims the name when the other host leaves.
What is exposed
Song and sermon titles, slide numbers, and the upcoming service order — in the clear, over plain HTTP, to anything that can reach the port. Also the ProPresenter machine's address and port, and the host's LAN addresses. Decide whether an unannounced sermon title or a baptism in the order matters to you before a service; if it does, the answer is the VLAN below, not a password.
Where this should live on the network
- Backstage PC, ProPresenter, and the display screens on a trusted A/V or management VLAN.
- Guest Wi-Fi kept off that VLAN. This is the single highest-value control here.
- A DHCP reservation for the backstage machine — which you want anyway so bookmarks survive.
- If you ever set a ProPresenter network password, treat it as a LAN-visible string: it travels in the query string of ProPresenter's own API on every poll, because that is the interface ProPresenter offers.
Run it standalone
For a machine that doesn't run Band Lineup — or to host the display without it — run the server on its own. Every other screen just opens a web page.
cd propresenter-app
node server.js
Then open http://localhost:7654 on that machine, press the gear (bottom-right,
appears when you move the mouse or tap), and enter the IP and port of the computer
running ProPresenter. That's it — the connection is stored on the server, so every
other screen that opens the page is already following along.
The startup log prints the addresses other screens should use, e.g.
http://10.1.1.42:7654. They're also listed in the settings panel under
Other screens.
Requirements: Node 18 or newer. No npm install, no dependencies.
ProPresenter side
Turn the network API on in ProPresenter ▸ Preferences ▸ Network. Note the port (1025 by default) and set a password there if you want one.
Run it as an app window
For the machine that should host the display, there's an Electron wrapper that starts the same server and shows the page in a window:
npm run kiosk
npm run kiosk -- --kiosk
The second form is true kiosk: no window chrome, fullscreen, for a dedicated screen. Either way the server still serves the rest of the building.
Options
| What | How |
|---|---|
| Different port | PORT=9000 node server.js |
| Lock the settings so viewers can't change the connection | PP_DISPLAY_READONLY=1 node server.js |
Move where config.json lives (a NAS, a shared path) |
PP_DISPLAY_DATA_DIR=/path/to/dir node server.js |
Per-screen looks — text size (Small → Huge), whether to show the playlist name, the progress bar, and whether to tidy titles — are set in the gear panel and saved on that device only, so a 65" TV and an iPad can each be sized for their own room.
Keyboard: f toggles fullscreen, Esc closes the settings panel.
Running it as a service
Any process manager works since it's a plain Node script. For example, with pm2:
pm2 start server.js --name stage-now-next -- --port 7654
What's in here
| File | Job |
|---|---|
server.js |
Serves the UI and pushes the live view-model to every browser over SSE. Standalone it polls ProPresenter itself; embedded it mirrors the client the Band Lineup app is already polling with |
config.js |
Reads/writes config.json (password obfuscated at rest — treat the file as a secret), and ranks which LAN address to bookmark |
mdns.js |
Publishes nownext.local so a bookmark survives a DHCP change. Zero dependencies |
public/index.html, public/app.js, public/styles.css |
The display itself and the settings panel |
main.js |
Optional Electron kiosk wrapper |
../propresenter-core/index.js |
The shared ProPresenter client — also used by the Band Lineup app |
API
Anything on the LAN can read the live state, which makes it easy to hang other displays or automations off the same feed:
| Endpoint | Returns |
|---|---|
GET /api/state |
{ state, status } — one JSON snapshot |
GET /api/stream |
Server-Sent Events: state on every poll, status on connection changes |
GET /api/status |
Connection info only |
GET /api/playlists |
Every playlist ProPresenter knows about |
GET /api/health |
{ ok, viewers, reachable } |
POST /api/connect |
{ host, port, password? } — tests, saves, and starts following |
POST /api/disconnect |
Stops following; keeps host/port for next time |
The two POST routes return 403 when PP_DISPLAY_READONLY=1, and 409 when the Band
Lineup app is hosting — a browser on the LAN must never be able to retarget or disconnect
the backstage app's own ProPresenter connection.
Notes
- The display auto-follows whatever ProPresenter is presenting — the live playlist and item come from ProPresenter itself, so there's nothing to pick each week.
- Slide totals respect arrangements. If an arrangement repeats a chorus, the total counts the repeat, so "Slide 41 / 43" always matches what the operator sees.
- Building a Windows installer (
npm run dist) needsnpm installin this folder first, and packages../propresenter-corealongside — keep the two folders siblings. The everydaynode server.jspath needs neither step.