-
-
Paste any Spotify, Apple Music or YouTube Music link. BridgeMyTunes spots the app straight away.
-
One link: whoever opens it picks their app and adds the playlist there.
-
Live matching. 7 of 7 songs found on Spotify in 3.1 seconds, nothing to review.
-
The result: a real Spotify playlist, no Spotify sign-in needed.
-
Switch apps: move playlists and liked songs from one service to another.
Inspiration
Music is how friends share what they're feeling, but every group chat has a Spotify person, an Apple Music person and a YouTube Music person. A shared playlist link only works for one of them. Everyone else gets "this content isn't available", or has to rebuild the playlist song by song.
We wanted sharing music to work like sharing a photo: send one link, and it just opens.
What it does
- Share anything. Paste a song, album or playlist link from Spotify, Apple Music or YouTube Music (or a whole list of song links copied out of the Spotify desktop app) and get one link.
- A song page shows where that exact recording plays on every service.
- A playlist page has an app switch and one "Add to …" button. Whoever opens it picks their app, and the playlist is rebuilt there.
- No sign-in to read. Public playlists and songs are read with our own app keys, so the person sharing doesn't need an account with us.
- Switch apps. Move playlists and liked songs from YouTube Music or Apple Music to YouTube Music, Apple Music or Spotify. If you're not signed in to the source app, paste any number of public playlist links instead.
- Live progress and review. Watch songs match in real time, then review the few that need a human: pick the right version, search the catalog yourself, or add a similar song Gemini suggests when the original isn't on that service.
How we built it
- Next.js 16, React 19 and TypeScript. Transfers run in the background and save progress to MongoDB, and the page updates live as songs match.
- One adapter per service behind a shared interface: the Spotify Web API (plus its public embed page for playlists without a sign-in), the Apple Music API with MusicKit JS (ES256 developer tokens signed with
jose), and the YouTube Data API v3 with Google OAuth. - A matching pipeline that tries the cheapest, most certain step first:
- Cached matches in MongoDB
- ISRC lookup (the code that identifies an exact recording)
- Metadata scoring: title 45%, artist 30%, length 15%, album 10%. Remaster naming, "feat." differences and soundtrack subtitles are cleaned out first. Live, acoustic, remix and sped-up versions, featured-artist differences and fan re-uploads lose points.
- Gemini suggests cleaner searches for songs the search missed: it strips "(Official Video 4K)", uses the real artist instead of a label channel, or tries the other script ("तुम ही हो" → "Tum Hi Ho").
- Gemini checks close calls, 8 songs per request, and returns the same recording or none, with a reason. It never swaps a clean version for an explicit one without asking.
- Anything still unsure goes to the user.
- MongoDB Atlas stores share links, transfers, connections and a match cache, so a song is only ever matched once.
- Vultr Cloud Compute runs the app at bridgemytunes.club: Ubuntu 24.04, Node 24 as a systemd service, Caddy for automatic HTTPS, and a ufw firewall. As a long-running server it has no 5-minute limit, so big transfers finish.
- Vitest: 29 tests covering the matcher, the link parser and the page parsers.
Challenges we ran into
- Every service names songs differently. "Bohemian Rhapsody - Remastered 2011" vs "Bohemian Rhapsody", "A & B" vs ["A", "B"], and YouTube titles full of "(Official Music Video)". Telling a remaster (same song) apart from a live version (a different recording) took a lot of rules and tests.
- YouTube has no ISRCs and a 10,000-unit daily quota, where one search costs 100 units. We cache every confirmed match and limit Gemini rescues to 25 per transfer.
- Spotify's Development Mode caps sign-ins at 5 test users. The house account and public-playlist reading let anyone use it anyway.
- Serverless time limits. Big transfers hit the 5-minute function limit and stalled. Running on a long-lived Vultr server removed that cap without changing the code.
Accomplishments that we're proud of
- One link that really opens on three different services, with no sign-in needed to view it.
- A matcher that finds the same recording, not just a song with the same title.
- Gemini used where rules fall short (messy video titles, non-Latin scripts), with a human always in charge of close calls.
- Live on our own domain, with HTTPS on Vultr, during the hackathon.
What we learned
- How differently streaming services describe the same recording, and why ISRCs matter so much.
- How to use an LLM as a careful judge: strict JSON schemas, confidence thresholds and a fallback model, instead of trusting it blindly.
- How to design around API quotas and platform rules rather than fighting them.
- How to deploy and run our own server: DNS, HTTPS certificates, a firewall and a process manager on Vultr.
What's next for BridgeMyTunes
- Run transfers on dedicated Vultr workers with a queue, so very large libraries move in parallel.
- More services: Tidal, Deezer and Amazon Music.
- Live-synced playlists that update on every app when the original changes.
- A browser extension that turns any music link into a BridgeMyTunes link.