efrain.fm

efrain.fm

I've always had a lot to say about music and nowhere good to put it. I wanted a living collection I could keep adding to. A collection that could surface songs I loved to any friends, family, or tech recruiters curious enough to explore it.

It's 740 songs (and growing) each one hand tagged and weighted on traits like mood, energy, era, and texture. It was a great excuse to ship something real with AI tools and to push my visual side with Three.js.

Embedded below for your convenience…

Unlocking grooves

The songs fall into nine "Grooves" such as Night, Cosmic, and Loss.

Each hides a keystone song with a spoken message from me, unlocked as you explore its cluster.

I wanted a way for visitors to explore the collection by theme while keeping it mysterious. Instead of straight-forward genres, release years, or artist names in dropdown menus I wanted to create an interactive object.

If you click on "Grooves" you'll see a floating, irregular form, a meteor? A brain? You can interact with it and clusters light up as you unlock them. It shows how many songs each cluster holds, too.

It does the work of a menu, but it feels like some alien remote control.

But what if they type…

The harder design work wasn't the interface, I got a prototype up in 20 minutes. The challenge was the conversation design. A chat interface can feel magical and free but there are many questions to answer:

  • When do you offer choices, when do you go quiet? 

  • What happens when your input has no matches? 

  • How do you prevent too many misses in a row? 

  • What happens when everything matching has already played? 

These answers shaped the feeling of the experience, maybe even more than the visuals.

The system redirects instead of guessing. Because no match feels better than the wrong match.

The matching system went through two rewrites. The final version uses a weighted trait vocabulary scored locally in JavaScript — because a binary tag system doesn’t capture intensity or contrast. A song can be mostly something, or barely something, and that difference matters. Claude Haiku extracts intent from free text, scores it against the traits, and a minimum threshold keeps weak matches from surfacing. 

Take me to the bridge…

Some connections can't be scored by a model, they're just stored as bridges in code. Kanye samples Gil Scott-Heron, and Gil Scott-Heron samples him back. "Disco Infiltrator" by LCD Soundsystem has a section that sounds unmistakably like "The Great Curve" by Talking Heads. Some Bright Eyes songs sit remarkably at home next to The Cure. These bridges make the automatic responses feel more human, because I put them there and an algorithm never would.

Adding a radio show

Recently I wanted an experience similar to a radio broadcast that could take the existing elements and present them in a more structured way.

I created a playlist with audio messages running in-between every 3 or 4 songs. It was a challenge fitting in a different interface in the same width, especially on mobile.

There's more to this story…

For the nitty gritty, like how I set up an AI fallback to make sense of unique words, let's set up a time to talk.

There's more to this story…

For the nitty gritty, like how I set up an AI fallback to make sense of unique words, let's set up a time to talk.