Cover image for Cadence

Cadence

2026

Web Development
Web Tool
Content Management
Member Portal
AI Tools
LLM
API Integration
View Live Demo
About the Project

Cadence is a self-hosted sheet-music platform I built for working ensembles. Point it at a pile of PDF scans and it sorts them into pieces, scores, and per-instrument parts, then serves them through a full-screen rehearsal viewer built for a tablet on a music stand — one page in portrait, a two-page spread in landscape, live re-layout on rotation, tap and swipe to flip, and a screen wake lock. Because the one moment the library has to work is a musician finding their part at rehearsal, the viewer is the default screen and library management is buried deeper in the nav. Set your section and part once and every piece defaults to it, so you never re-filter past the other instruments.

The Rehearsals home is a list of concerts, each with its ordered setlist — the July 21st concert's ten pieces, the dates after it — that I tap to jump straight into rehearsal mode, scoped to the current band (Lake Stevens Community Band here) with a per-user sign-in. View Music is the library proper: it renders the real scanned score in the viewer — the Adagio from Concierto de Aranjuez, decorative publisher cover and all — alongside a breakdown of the full score (pp. 1–29) and each solo part (Solo Flugelhorn, pp. 30–42), with Listen for a linked reference recording and Add to queue for continuous playback. The stat tiles across the top — 29 pieces, 612 docs, 58 scores, 543 parts — are one real ensemble's actual library. It installs as a PWA.

The stack is a deliberate refusal: a Python 3.12 backend on the standard library only — no Flask, no FastAPI, no requirements.txt — over SQLite with a hand-written schema, and a vanilla-JS front end with no framework and no build step, with pdf.js vendored locally. The piece I'm most pleased with is the part-book splitter: publishers ship one PDF holding the conductor score followed by every instrument's part, and it segments them deterministically from extracted text rather than vision, keying pages by their cleaned header and collapsing consecutive matches into page ranges, with OCR as the fallback for scans with no text layer. Classification runs against a self-hosted vision model but always computes a filename heuristic first and falls back to it on any error — it never fails closed — and that heuristic encodes real ensemble domain knowledge, sorting parts in score order rather than alphabetically. Annotations are stored in normalized page-box units so pen, highlighter, and text marks stay locked to the music across zoom, resize, DPI, and two-page mode, with a plugin seam that percussion and timpani modules register drum-tuning widgets into.

It's in real use by one ensemble against a real library on a real concert deadline — the data-repair scripts in the repo are the fingerprint of production data hitting edge cases — with 103 Python and 39 JS tests. Honest caveats: offline sync is built but currently paused behind a self-unregistering kill-switch worker after a cache-first version pinned clients to stale shells, waiting on a network-first rewrite; the Android viewer is a day-one scaffold that never went further; and the Google Drive importer is secondary to the ZIP/folder path that overtook it. Built Jun–Jul 2026.

Image Gallery

Cadence gallery image 1
Cadence gallery image 2