-
-
Logo: the Batus logo thumbnail from before.
-
Landing page: "Tell it what you are going through
-
Heartbreak and the two moods: Calm me and Lift me up.
-
Safety screen: shown when someone types that they want to die.
-
Phone view: the mobile layout.
-
How it works: you, then Qloo's taste graph, then real songs.
-
"Batus never invents music": the guarantees, with the 74 tests mentioned.
Inspiration
When my mind won't stop, I don't reach for advice. I put on praise and gospel music, Nigerian and international, and within a few songs my chest loosens. The trouble is that in that exact moment I can't think. I don't remember who to play, and every calming music playlist is the same global list that has nothing to do with my taste.
That gap is Batus. Overthinking and heartbreak both hit people in moments when they are least able to search, choose or decide. Generic playlists and chatbots answer with averages. What actually helps is your own music, and Qloo's taste graph is built to know what people with your taste love.
What it does
Batus is a comfort companion for two situations: Worry & overthinking and Heartbreak. Each has two modes, Calm me and Lift me up.
- You say what you are going through (optional, never saved, never logged) and add a few artists you love, from any genre, language or country.
- Batus asks Qloo for artists people with your taste love, nudged by music mood tags and an optional location. It also finds a podcast and a show from the same taste.
- It builds a set of real songs from those artists and from yours, scored for the mood. Each song has a 30-second preview and links to play the full track.
- You can add songs to your own playlists (one per mood), saved on your device.
Safety comes first. If someone writes that they want to die or hurt themselves, Batus stops the music and shows human help (findahelpline.com, 988 in the US, Samaritans in the UK and Ireland).
How I built it
- Next.js (App Router) on Vercel. No account and no database.
- Qloo hackathon API:
/searchfor artist autocomplete and IDs,/v2/tagsto resolve mood keywords into music tags, and/v2/insightsfor artists, podcasts and TV shows (withsignal.location.query). A small client handles the 5 requests/second limit, retries and caching, and shows the real error when Qloo fails instead of "unavailable". - Real songs: Qloo returns taste, not tracks. So songs come from Apple's public iTunes Search API. Batus loads each artist's deep catalogue and scores tracks by mood, so the same artists give different songs for different moods and different check-ins.
- Optional Claude layer: when an Anthropic key is set, Claude reads the check-in and a numbered list of real songs and chooses by ID, with a one-line reason each.
- The thesis, enforced in code: Batus never invents music. Artists come only from you or Qloo. Songs come only from the catalogue. The AI picks by ID, and any ID it makes up is dropped. Tests prove this.
- Layered safety: wide keyword patterns (slang, disguised spelling) stop everything with no outside call; then a Claude screener (crisis / concern / ok); then backstops in the pipeline. Softer distress adds a caring note above the music.
- 74 automated tests, CI, an audit log of findings with fixes, and a public MIT-licensed repo.
Challenges
- "Qloo is unavailable." My first version swallowed errors. I rebuilt the client around Qloo's real behaviour (404 means no results, 400 means a bad query, rate limits) and added a
/api/diagnosepage that shows the true status of every call. - The songs were always the same. The pool was each artist's biggest hits, so every mood got the same list. I fixed it at the root: deep catalogues, the user's own artists in the pool, mood scoring with variety, a memory of recent songs, and a "Different songs" button.
- Safety from the root. A first test of "I wish for death" returned a song. Safety became layered and was moved to run before any recommendation work.
- Honest limits. iTunes only allows about 20 searches a minute per IP, so each check-in is capped and cached. Neither Claude nor the mood scorer hears audio or reads lyrics, so a pick can miss.
What I learned
- A taste graph is most useful when it is central to the result. Here, without Qloo there are no taste-matched artists, no mood-tag steering and no podcast or show matches.
- Showing real errors and writing a self-test page saved more time than any extra feature.
- For an emotional product, safety and honesty are part of the design, not a footer.
- A strong thesis ("never invents music") is easiest to trust when tests enforce it.
What's next
- Check which mood tags Qloo resolves best for each theme and tune them.
- Measure how well Qloo covers gospel and praise artists from across Africa.
- Add more situations beyond worry and heartbreak.
- Let people save a full playlist to their streaming app.
Built With
- ai-agents
- anthropic
- claude
- css
- github-actions
- itunes-search-api
- javascript
- nextjs
- node.js
- playwright
- qloo
- qloo-api
- react
- recommendation-engine
- taste-graph
- tool-use
- vercel
Log in or sign up for Devpost to join the conversation.