Setlist
Starting pitches and a metronome for an a cappella choir, built to run on stage during a concert.
Live app: https://dffmonolith.github.io/setlist/
Guides: Quick start for directors · For singers: using the join link
- Gives the group its starting pitches for each song from an embedded piano sample library, so once it's loaded it works with no internet connection.
- Steps through the concert's running order with one tap.
- Keeps several named setlists, one per concert. Pick one at the top of the screen; the newest concert built into the file becomes the current one when it first arrives.
- Each setlist (titles, keys, starting pitches, tempo, ending chord) is plain delimited text. You can edit it in place or paste in a whole new one.
- Rehearsal Mode names the song's key in large type ("D minor") and shows a four-octave piano keyboard (C2 to B5, the same for every song): the key's notes are named and marked with their scale degree (I, ii, iii … or i, ii°, III … in minor), the tonic is outlined, dots mark the starting pitches, and every key plays, accidentals included.
- Metronome (visual or audible) with large tap targets for adjusting tempo mid-performance.
- Optional ending chord per song: the ▶ End button plays it as a block chord, so you can check where the choir finished (the end is often in another key).
- Tuner: sing or hold a note and see its name and how many cents sharp or flat it is. The microphone is on only while the tuner is open. It reads one pitch, so with the whole choir singing it follows the loudest voice.
- 🎯 Check the end chord (Rehearsal Mode): listens for three seconds while the choir holds its last chord and says how far off it is, overall and note by note.
- From the score (needs a scores server, see below): for songs linked to the choir's MusicXML scores, a row of point cards marks the likely starting places (rehearsal letters, fermatas, everyone breathing, a part coming in, key and tempo changes…), each with its bar, the reason and the chord; the song's End chord is the last card. Pick any bar and beat; the staff shows one or two bars with the words and the beat lit, and a tap on a beat or a note starts there or plays that part. Bring out one part over the others, play the Starting chord, or Play from here for a phrase, a number of bars or to the end, with Pause/Resume and a Playback speed from 50% to 150%. Scores are kept on the device, so this works offline too.
- Points for the whole choir: the director picks which point kinds count (one checklist for every song) and can hide or add points in a song on any beat (✎ Edit points). The choices sync to every singer's device; a singer can still choose their own kinds.
- Join link: the director sends one link; a singer taps it and is connected to the scores with Rehearsal Mode on.
- Concert lock (🔒 Lock): hides everything a stray tap could change and adds a big Next button; press and hold the lock bar to unlock.
- Just for Me: plays everything about 20 dB quieter, for checking a pitch with the device at your ear. It always starts off.
- Share a setlist (Edit → Share): sends a link plus the plain text. Opening the link offers to add the setlist; in the installed app, paste the link into Paste/Copy Text and tap Apply.
- Keeps the screen awake while the app is open ("☀ awake" by the version number).
Single self-contained HTML file in vanilla JS and the Web Audio API, with no build step and no dependencies. Piano: the Salamander Grand Piano samples (Alexander Holm, CC BY 3.0), embedded.
Scores server
From the score, point syncing and join links talk to a small PHP endpoint on the choir's own web host, which serves the MusicXML files (.mxl, .mxml, .musicxml) behind two tokens: one for the director, one for singers. That endpoint isn't in this repository yet; everything else in the app works without it.
Install on iPhone / iPad (works offline)
- Open the live app in Safari while online.
- Tap Share → Add to Home Screen.
- Launch it from the home-screen icon once while still online. When "✓ offline ready" appears next to the version number, it's fully cached and will run with no connection.
On iOS 16.4+ the pitches play even with the Ring/Silent switch on.
Note: on iOS the home-screen app keeps its own storage, separate from Safari, so a setlist edited in Safari won't appear in the installed app (and vice versa). Copy it across with Edit Setlist → Paste/Copy Text.
You can still save setlist.html and open it directly as a file; it just won't get the home-screen install or auto-updates that way.
Releasing a new version
Bump CACHE_VERSION in sw.js (and the version tag in setlist.html). To ship a new concert, add an entry with a new id to BUILTIN_SETLISTS in setlist.html (mark it isDefault: true to make it current when it arrives); changing an existing entry won't reach devices that already have it. Installed copies download the new version in the background and show an update ready ↻ button; nothing switches over until someone taps it or fully closes and reopens the app, so an update never lands mid-concert.