Dusty Grooves
If it ain't vinyl, it ain't real.
What it is
Dusty Grooves is a browser music player disguised as a record shop that never made it out of 1983. You walk up to the storefront, step inside, and the owner, Big Tony, helps you find a record before dropping the needle on it.
Built in React, the app's personality comes from a small state machine. Every state maps to one of Tony's poses and lines, so searching, loading, playing and even failed searches feel like part of a conversation. No accounts, no playlists, no sign-up. Just search, pick a record and listen.
The problem
Building the shop was the easy part. Getting sound out of it was the whole project.
My original plan was simple: find a free audio source and point an audio element at it. By the time I built the app, every service I intended to use had either disappeared or returned unusable links. The few that still worked generated URLs that browsers couldn't play directly because they only worked inside YouTube's own player.
I had a finished shopfront, a finished character and a working search, but no reliable way to play a track.
The decisions
Finding the song, not the stream
The solution was to stop chasing audio files altogether. Instead, each track is resolved to a YouTube video and played through YouTube's own player.
A small Cloudflare Worker queries community Invidious instances on the server, avoiding browser cross-origin restrictions and returning clean JSON. It keeps a short list of instances and automatically tries the next one if a host goes offline. Because that list lives in the Worker, I can swap hosts without redeploying the site.
Picking the right one
A search rarely returns a single obvious match. Results are often live performances, remixes, karaoke versions or hour-long loops, so every candidate is scored before playback.
| Signal | Weight |
|---|---|
| Track name in the title | +10 |
| Artist in the title or channel | +10 |
| "Official" in the title | +5 |
| Verified channel | +3 |
| View count, by tier | +1 to +3 |
| Remix, cover, karaoke, sped up | −8 |
| Live, concert, or acoustic | −4 |
| Under 30 seconds | −10 |
| Over ten minutes | −6 |
Track and artist matches carry the most weight, while official uploads, verified channels and high view counts help identify the best candidate. If the highest-scoring result doesn't reach five points, the app refuses to play anything rather than risk choosing the wrong song.
Playing it
Playback happens through a hidden 1×1 YouTube IFrame player.
This is the biggest compromise in the project. YouTube doesn't offer an audio-only mode, so the app streams a tiny video while using only its sound. Forcing playback to 240p keeps bandwidth low, while the interface polls the player four times per second because the IFrame API doesn't provide a time-update event.
Cover art
Album artwork comes from Last.fm where available, falling back to the video's YouTube thumbnail and finally a default sleeve. Every track has artwork, even when music databases come up empty.
What I'd do differently
The weakest part of the project is playback recovery, and I know exactly why. When YouTube blocks a video, only a small number of error codes trigger another attempt. The most common failure, disabled embedding, isn't one of them. Worse, retries repeat the same search and usually land on the same blocked video.
The proper fix would be to keep the ranked results and move to the next candidate instead of starting over. I'd also treat blocked embeds as recoverable errors.
I'd cache successful matches too, since searching for the same track currently repeats the whole lookup process.
The larger issue, though, is the foundation itself. Playback depends on public Invidious instances that I don't control, and that list keeps shrinking. At the time of writing, only one reliable host remains. If I rebuilt the project today, I'd either pay for a supported audio API or narrow the scope to a fixed music library that I could host myself and guarantee would always work.