Part 1 — I Just Wanted a Better Music Player
There is a very specific kind of frustration that slowly builds over years of using software that almost does what you want.
Not catastrophic frustration.
Not rage.
Just a thousand tiny compromises.
Music apps that:
treat your carefully curated library like disposable streaming content
lose metadata
struggle with large local collections
feel sluggish with FLAC libraries
hide your files behind proprietary abstractions
or simply refuse to respect the idea that your music collection is something personal.
That frustration eventually turned into Needle.
At the beginning, the idea was almost modest:
Build a proper local-first desktop music player.
Nothing cloud-based.
Nothing social.
Nothing algorithmic.
Just:
fast local playback
beautiful library management
proper metadata handling
support for lossless audio
and software that respects ownership.
The stack itself was fairly modern:
Tauri
React
TypeScript
Rust
mpv for playback
The goal was not to reinvent Spotify.
The goal was to reclaim the experience of owning a music library.
And honestly?
That part alone would have been enough.
But personal projects have a dangerous tendency:
Once they become genuinely useful to you, your standards rise dramatically.
You stop thinking like:
“Can this technically work?”
And start thinking:
“What would make this feel truly right?”
That question changes everything.
Because eventually one very specific thought appeared:
What if playback state synced across devices?
That was the moment the project quietly crossed an invisible line.
Because synchronized playback does not belong purely to a desktop app anymore.
It requires:
shared state
identity
persistence
session management
communication between devices
In other words:
A backend.
And just like that, the simple local-first desktop player suddenly became the foundation for something much larger.
The funny thing is that none of this was planned.
There was never a grand architecture document.
No “roadmap toward platformization.”
No startup pitch deck.
Just:
“This missing capability annoys me enough that I should solve it properly.”
That single mindset turned out to be responsible for everything that came next.