Playhead
I've been scrobbling on Last.fm for over a decade and I have always wanted to build something with their API. I wanted something that could look at my actual listening patterns, find the threads running through them, and pull me toward artists I genuinely don't know yet. So I built it: www.play-head.com
What Playhead Does
You connect your Last.fm account, pick a time window (last week, last 6 months, a custom range), and Playhead analyzes your top artists from that period. It profiles each one — tags, similar artists, streaming counts — and groups them into three "listening clusters" that represent distinct lanes of your taste.

Pick a cluster, and Playhead generates up to four artist recommendations that fit the vibe but are filtered against your listening history. If you've already played an artist more than a handful of times, they won't show up. The goal is genuine novelty — not "you listened to Radiohead, here's Thom Yorke's solo stuff."

The Discovery List
This was the feature I wanted most. Every music recommendation tool I've used gives you a list and then... that's it. You forget about it. The Discovery List lets you save recommended artists and then tracks your progress — "Plays since saved: +15" — so you can see whether you're actually following through on discovery.

It preserves the context from when you saved the artist: the blurb explaining why they were recommended, a starting album, the tags that connected them to your cluster. It's less "here's a name" and more "here's a name, here's why, here's where to start, and here's how much you've listened since."
I built this because I know myself. I'll hear about an artist, think "I should check them out," and never do it. Having a persistent list with progress tracking turns passive intent into something I can act on. It's a small thing but it changes the behavior.
How It Works Under the Hood
The recommendation engine is deliberately split into two layers. All the actual ranking — candidate generation, scoring, novelty filtering — is deterministic. Playhead pulls similar-artist data from Last.fm, scores candidates on tag overlap, how many of your seed artists vouch for them, and a novelty bonus for truly unknown artists. No LLM touches the ranking.
LLMs (OpenAI, specifically gpt-4o-mini) only handle two things: grouping your artists into labeled clusters with human-readable descriptions, and writing the short blurbs that explain why a recommended artist fits. If the LLM call fails, deterministic fallbacks kick in — keyword-based clustering and template blurbs. The app still works without AI; it just reads a little less editorially.
I was intentional about this boundary. I wanted AI to make the experience feel polished, not to be the engine (but I am experimenting with that!). The data and the math come from Last.fm's actual similarity graph and your actual listening history.
The Stack
Next.js on Cloudflare Workers (via OpenNext), Prisma with D1 for storage, and Last.fm's API for all the music data. Analysis and recommendation jobs run asynchronously through Cloudflare Queues — the analysis can take a few seconds depending on how many artists need profiling, and I didn't want users staring at a spinner on a blocked request.
One of the more involved pieces was the weekly history backfill system. When you connect your account, Playhead starts ingesting your entire scrobble history week-by-week in the background. It needs to fit within Worker time limits, so each job processes in batches with heartbeats and a watchdog to rescue stuck jobs. All of this runs so that when you come back later, Playhead has a richer picture of what you already know.
What's Next
There's a long list. Better onboarding, richer cluster exploration, playlist export, more granular time selection, discovery and recommendation paths based on a single artist. The core loop works — analyze, discover, track — but there's a lot of room to make the discovery experience deeper and more engaging.
For now, it's the music discovery tool I wanted. I'm using it, and my Discovery List has artists on it I wouldn't have found otherwise. That was the whole point.