From a simple idea about Black music representation to a full similarity engine, 5,000+ artist database, and daily puzzle game. Here's everything — no gatekeeping.
I was obsessed with Semantle and Wordle variants. But every music version I played was the same: guess the Taylor Swift album, guess the pop song. Nothing that spoke to where I came from or the music I actually loved.
So I built my own. A daily puzzle game where the artist pool is the entire African diaspora — Afrobeats, grime, jazz, soul, dancehall, hip-hop, highlife, Afro-Brazilian, drill, soca. Music of the diaspora. 5,000+ artists, one hidden every day, and you find them through musical proximity rather than exact naming.
This is the core of the game. When you guess an artist, the engine computes how musically similar they are to the hidden answer and returns a rank from 1 to however many artists are in the pool.
The engine uses 7 dimensions, each weighted based on how much signal they carry:
Each artist has a 6-dimensional "mood vector" — a set of numbers representing how their music feels. Things like energy, darkness, danceability, spirituality. These aren't just tags — they're continuous values, so you can compute actual mathematical distance between artists using cosine similarity.
This is why the game feels "right" even when two artists share no genre tags. A FROZEN Afrobeats producer might still be musically adjacent to a UK soul vocalist if their mood vectors align.
// Cosine similarity between two 6-dimension mood vectors
function cosineSim(a, b) {
const dot = a.reduce((s, v, i) => s + v * b[i], 0);
const magA = Math.sqrt(a.reduce((s, v) => s + v*v, 0));
const magB = Math.sqrt(b.reduce((s, v) => s + v*v, 0));
return dot / (magA * magB);
}
// Full similarity formula
function artistSim(a, b) {
return cosineSim(a.mood, b.mood) * 0.33
+ (a.cat === b.cat ? 1 : 0) * 0.19
+ collab(a, b) * 0.16
+ jaccard(a.era, b.era) * 0.13
+ (a.region === b.region ? 1 : 0) * 0.08
+ jaccard(a.type, b.type) * 0.06
+ jaccard(a.i, b.i) * 0.05;
}
The similarity score gets translated into a temperature — a human-readable indicator that tells you whether you're burning hot or ice cold.
Temperature also determines how much detail the feedback gives you. A SCALDING guess might say "They've worked together directly. Both Atlanta trap — heavy 808s, melodic flow. Active 2010s–2020s." A FROZEN guess gives you one bare directional fact. Reveals skill, rewards curiosity.
There's no existing dataset of Black music artists with the fields I needed. I had to build it. Here's the full pipeline — from generation to enrichment to deployment:
I went in assuming MusicBrainz would have everything. It doesn't. Some real coverage numbers that surprised me:
Field MusicBrainz Wikidata ───────────────────────────────────────────── Genre tags ~70% — Origin city/country ~65% — Associated acts ~50% — Instruments ~40% — Record labels ~5% ~70% (P264) Influences ~5% ~35% (P737)
The label relationship issue was a database design quirk — MusicBrainz stores "this artist founded this label" not "this artist was signed to this label." A rapper's label-rels return nothing unless they own their own label. Wikidata's P264 property has this right. Lesson: always test coverage with a sample before you architect around an API.
The initial database had 2,404 artists. To hit 5,000+ and improve representation of under-served regions, I set up an overnight scheduled task. By morning: 5,002 artists — 2,598 new additions across East Africa, Francophone West Africa, contemporary Afrobeats, UK drill, Caribbean dancehall, and Latin Black music.
Live leaderboard via Vercel KV. Sorted by guesses then time. DNFs sorted below finishers. Resets at midnight. Your score lives alongside everyone else who played today.
Coloured squares showing each guess's temperature. Pipe-separated trail for short games, rows of 10 for longer ones. WhatsApp renders it as a blockquote. No spoilers.
localStorage tracks whether you've played today. Return players see the artist reveal, their score, and can re-share — but can't replay. Keeps the daily ritual clean.
Clues unlock every 10 guesses OR every 1 minute — whichever comes first. Always visible but greyed out. From a nearby artist to your top 4 closest options.
Interactive collapsible D3 tree of all 50+ genres. After completing a game, the tree opens focused on today's artist's genre so you learn where they sit in the diaspora.
Win screen shows the artist's photo (from Spotify or Wikipedia), genre/era/region, an audio preview, and a Wikipedia bio. The reveal should feel like a discovery.
After posting your score, you get a leaderboard rank and a rank title. Top 6 are celebratory. From #7 down they get progressively more insulting:
Every game produces a shareable text card. The emoji trail is the game's "spoiler-safe fingerprint" — you can see exactly how someone played without knowing the answer:
The > prefix makes WhatsApp render the squares as a blockquote — visually distinct from the rest of the message. Pipe separators keep short games readable. Longer games pack into rows of 10 automatically.
This wasn't a straight line. Here's the actual sequence of what got built and what broke along the way:
Basic Semantle-style game with a flat artist list and Jaccard genre overlap as the only similarity signal. Worked, but genre overlap is too blunt — Wu-Tang Clan was ranking at #1 for DMX.
Replaced genre Jaccard with 6-dimensional mood vectors and cosine similarity. Immediately more musical. Artists that feel similar actually rank close. This was the breakthrough.
Enrichment scripts pulling genre tags, origin, associated acts, record labels, and influences. Learned that MusicBrainz label coverage is ~5% — pivoted to Wikidata P264/P737. Database grew from 2,404 to 5,002 artists.
Three-screen win modal: Artist Reveal → Score + Share → Explore. Vercel KV leaderboard. Daily lock via localStorage. Once-daily ritual established.
D3 collapsible genre tree replacing the force-directed graph. Share card emoji trails. Rank title ladder. Ko-fi support card with live webhook. Artist photos + bios. 5-clue system.
I didn't reach for a framework. The game is a single HTML file, some Vercel serverless functions, and Vercel KV for the leaderboard. That's it. No build step. No npm install. Deploy on push.
The entire game — all screens, all logic, all CSS — lives in one index.html. Fast to iterate, easy to read, zero build complexity.
API functions for the leaderboard, Spotify image fetching, Ko-fi webhook, and the daily artist picker. Node.js, zero config.
Leaderboard persistence. Daily entries expire after 36 hours. Ko-fi donation totals stored and retrieved without a database setup.
Only external library in the game. Powers the collapsible genre tree — hierarchy, transitions, zoom, pan, focus animations.
TOP SELECTA isn't a standalone project. It's one of several things I'm building under the banner of Black Music Multiverse — a connected world of interactive experiences celebrating the music, stories, and culture of the African diaspora.
Think: a 3D world where each district is a different experience. You walk into a tavern and it's a strategy game. You enter a shrine and hear an audio story set in an Afro-utopia. You find a crypt and it's an art cinema. TOP SELECTA sits in this world as the music discovery game you stumble into off the street.
Everything is free. No ads, no paywalls, no data collection. Just things I care about, made with care, shared with anyone who wants them.
Building this has cost real money. Not complaints — just honesty:
About £247 total and counting. I'm not asking for much — even £1 or £3 genuinely helps keep this going and makes the next thing possible. Ko-fi has the full story behind the project and where it's headed.