Rank your Spotify library by voting between two songs at a time. Songrank pulls about 128 tracks out of your listening history, shows you pairs, and you tap the one you like more until it knows your real top 25. At the end it writes "My Top 10" and "My Top 25" back to your Spotify as playlists with generated cover art.
Try it at jackhomer.com/songrank
Songrank does not ship with a Spotify API key. Before your first run you register a free Spotify developer app of your own and paste its Client ID into the setup page. It takes about ninety seconds and the app walks you through every step.
The reason is a Spotify limit rather than a design preference. An app in Spotify's development mode only works for people you add by hand to a short allowlist, so one shared key would let Songrank serve a few friends and nobody else. Your own key means it works for you, permanently, for free.
Two things about the setup worth knowing up front:
- Spotify's dashboard asks for a redirect URI. The setup page shows you the exact string to paste, computed from wherever you happen to be running it. On the hosted site it is
https://jackhomer.com/songrank/callback/. - After creating the app, add yourself under Settings → User Management with the name and email exactly as they appear on your Spotify account. Skipping that is the most common reason "Save to Spotify" fails later.
You can ignore the client secret. Songrank uses Authorization Code with PKCE and never needs one.
Nowhere. Songrank is a static site with no backend. Your Client ID and access tokens live in localStorage in your browser, and every Spotify call goes straight from your browser to api.spotify.com with your own token. I never see your music, your keys, or your rankings.
The page does load Umami for anonymous visit counts, and 30-second song previews are looked up through Apple's iTunes Search API, because Spotify stopped populating preview_url for most tracks in late 2024.
The pool is built from five signals in your account, in priority order: your all-time top tracks, your last six months, your last four weeks (capped at five tracks so a recent binge can't dominate), Spotify's own recap playlists like Wrapped and On Repeat, and any track appearing in at least a quarter of your own playlists. Albums are capped so a single record can't flood the pool, and the same song under two different releases is deduped by title and primary artist. A brand-new account with no history falls back to a daylist, then to Today's Top Hits.
Voting is binary insertion against a ranked list with a floor at 25. Each new track is compared first against whatever sits at position 25 — lose that and it's gone in a single vote, win and it gets binary-searched into place in about five more. A full 128-track pool lands around 370 votes, roughly twenty minutes of tapping, against the ~900 a complete sort would need. There's also a 64-track option if you want it shorter. Progress is saved to localStorage, so closing the tab is safe.
Only the top 25 is decided by your votes. Tiers below that are the rest of the kept pool in Spotify-signal order.
- Save to Spotify — creates private "My Top 10" and "My Top 25" playlists. Cover art is composed in-browser on a
<canvas>as a 2×2 or 3×3 mosaic of album art and uploaded with the playlist. The upload is best-effort; the playlists are created either way. - Share cards — a 1080×1920 PNG of any tier (10, 25, 50, 100, 128) as a numbered list or a dense mosaic.
- Bracket image — your top 16, or top 8 for a shallower pool, drawn as a seeded bracket with connector lines and a champion badge. It's a picture of the finished ranking rather than a record of how the votes went, since the ranker is binary insertion and not single-elimination.
- Predict my top 10 — send someone a
/predict/?t=…link and they see your top 10 shuffled, drag it into the order they think you picked, and get a score out of 100 (60% from pair ordering, 40% from exact placements). They need no Spotify login; track metadata comes from Spotify's public oEmbed endpoint. - Manual reorder — drag the final list into the order you actually want and it sticks.
- Group mode — 2 to 4 people in total, each contributing a slice of the pool. The state travels in the URL, so there's still no backend, and the last person to go ranks the merged pool.
Before voting starts there's a sub-in screen showing the whole pool, where you can drop tracks you don't care about and search for ones it missed, one at a time or by importing a whole playlist.
npm install
npm run dev # next dev, http://localhost:3000
npm run build # static export
npm run typecheck
npm test # vitestAdd a second redirect URI to your Spotify app pointing at your dev origin. The /setup page prints the exact value to copy while you're running it, so use that rather than guessing. A Spotify app can hold several redirect URIs, so your local one can sit alongside the hosted one.
All static, trailingSlash: true.
| Path | What it does |
|---|---|
/ |
Landing |
/setup |
One-time: paste your Client ID |
/callback |
PKCE token exchange |
/pool |
Review the pool, drop and add tracks; also hosts group mode |
/compare |
This-or-that voting |
/reveal |
Ranking, playlist export, share cards, bracket, predict link |
/predict |
Public — a friend guesses your top 10, no auth needed |
Next.js 16 with output: 'export', TypeScript, Tailwind v4, and @dnd-kit for dragging. PKCE is built on Web Crypto with no shims. Deployed to GitHub Pages by .github/workflows/pages.yml, which sets NEXT_PUBLIC_BASE_PATH so links resolve under the repo path.
Background and build notes: jackhomer.com/projects/songrank
