Répertoire
Classical piano catalog and advisor.
Origin
Every pianist hits the same wall: you finish a piece, and then you lose a week deciding what to learn next. The advice available is either a teacher you may not have, or a forum thread arguing about whether the Revolutionary Étude is grade 8. I wanted something that would take my actual level and what I had already played, and answer the question — with its reasoning shown, so I could disagree with it.
"Deciding what to play next shouldn't be the hard part. I built it because I wanted it to exist."
Scale
- 10,000+
- Pieces catalogued
- 1–9
- Henle difficulty range
- 0
- Human review steps in curation
How it works
Discovery
New candidates found and screened cheapest-check-first
Entrance gate
Anything not a single solo piano piece is rejected before it is written
Catalog
10,000+ pieces with difficulty, key, period, form and tags
Curation
Re-verified on a schedule, most-played pieces most often
Scoring
Deterministic engine ranks the catalog against your level and history
Explanation
Every recommendation says, in plain English, why
The hard part
Not the recommendation engine — the data underneath it. A scoring engine is only as good as the catalog it reads, and a public-domain music library is messy: collections listed as single pieces, organ works filed under piano, the same sonata under four spellings. Getting per-piece data reliable enough that I would act on it myself meant building a pipeline that polices the catalog continuously, deletes carefully, and can be fully reversed when it gets something wrong.
Decisions
A deterministic scoring engine rather than letting a model pick
A recommendation you cannot explain is not advice. Deterministic means every ranking can be traced, argued with, and corrected.
Quality over quantity as the catalog's governing rule
A smaller correct catalog beats a larger careless one. Being obscure is never a reason to remove a piece; being wrong is.
Two strikes and thirty days before a deletion is real
The cleanup runs with no human review step, so it has to be recoverable by design rather than by discipline. Every change is logged and a whole run can be reverted.
Leaving a performance slot empty rather than filling it badly
The old approach attached the first search result blind, which is how one piece ended up playing a two-hour compilation by a different composer. An empty slot is better than a wrong video.
Constraints
- Solo, unpaid, so anything that needed a team or a licence was out
- Public-domain scores only, which meant building on IMSLP's catalog rather than a clean commercial dataset
- Difficulty ratings estimated independently against the Henle scale — the real ratings are licensed
- The data had to be trustworthy enough to act on: a wrong difficulty sends someone into a piece that hurts them
Stack
Application
- Next.js
- React
- Tailwind CSS
- Framer Motion
- Base UI
Data
- Supabase (catalog)
- Firebase (accounts)
Operations
- Vercel
- Sentry
- GitHub Actions
Sources
- IMSLP
- Henle scale (estimated)
- YouTube