2024-Present
A local music system that feels like your favorite streaming app
Personal project
Problem
How can a self-hosted music library feel immediate across devices without asking its owner to manage a distributed system?
Outcome
The ability to carry a personal library that lives on one device wherever you go, and keep working on it from wherever you are: a desktop hub and iOS/Android companions joined by one personal networking layer, with no cloud and no third party in the middle.
Context
I am a DJ. The music I care about is not a saved tab in a streaming service. It is a local archive built over years: purchased files, rips, edits, metadata fixes, Rekordbox preparation, half-finished playlists, notes for a future set. It lives on a computer because that is where the storage, the work and the responsibility live.
Most software makes that archive choose between two bad versions of convenience. Keep it local and accept that it stays trapped on one machine, or copy it into a cloud service and let a different product become the authority. Tape Music Suite starts from a different premise: the library should remain mine, while the experience can still be as immediate as the music products people are used to.
I am designing and building the product model, interfaces, pairing, playback, routing, networking, releases and real-device QA. That breadth matters here because a clean mobile screen is not enough. The experience only works if the catalogue, its state, the network route and the playback behavior agree with each other.
Before building anything, I spent years actually living inside this problem as a user, and went through every existing product in this space to understand the gap it actually left open. Almost all of it is open source, and almost none of it is cohesive end to end: one project is a personal streaming server and nothing more, a scattered set of community-built iOS and Android apps connect to it, and a further layer of tools bolts features onto those same servers and ships its own releases. Every one of those servers still expects its owner to have real technical knowledge and to keep something running correctly on a machine somewhere. I mapped this as a product problem from the two angles I know personally, DJ and collector, traced the actual workflows, and looked at why Rekordbox, Serato and the rest of commercial DJ software have never earned the trust of people who want real control over their own library. Tape starts from that opening: one opinionated structure for how a personal library should behave, held consistently across every app in the set, from the hub to the phone in your pocket.
The product problem
A local-first music product has a harder job than a normal media app. The same track can be present on the hub, available through the local network, reachable through a paired route, temporarily cached, offline, reconnecting, or genuinely unavailable. Those are not implementation details when the user has pressed play or is about to build a set.
The product has to absorb this topology without lying about it. A user should not have to become a network operator in order to hear their own music, but the interface cannot pretend every file is equally ready at every moment either. The decisions below are the product structure I am using to hold that tension.
Keep one catalogue, not two libraries
The first decision is architectural and experiential at once: the desktop hub is the authority for the archive. The phone is not a synced subset with its own drifting truth. It is a companion that can browse, organise and play the same library.
That sounds simple, but it changes the whole product. A playlist made while walking through the city has to mean the same thing when I return to the desk. A rating, saved track, cover, metadata correction or inbox action cannot become a phone-only opinion that needs a reconciliation ritual later. The library already has a history; the product should not make the owner choose which copy of that history is real.
The cover image is deliberately mundane proof of this direction. It shows the same catalogue on desktop and mobile. The point is not that both interfaces look alike. The point is that they are working on one musical world.
Use playlists as the organising layer
Folders are storage; playlists are thought. A serious archive cannot be faithfully expressed by a single file path. A track can belong to a label, an artist collaboration, a year, a mood, a city, a warm-up set, a late-night set and a note to revisit. Forcing that graph into one folder hierarchy only hides the problem under tidiness.
Tape therefore treats the folder structure with respect without making it the primary way a person thinks. Playlists, saved tracks, listening history, ratings, tags and filters let someone build their own working vocabulary across devices. This is especially important for DJs: collection and preparation happen everywhere, while the archive and the final performance tooling still have to remain reliable.
Pair without exposing networking
Pairing is not a settings chore. It is the moment a person decides that this phone can act on their library. The flow has to establish trust between a hub and a companion through an invitation, recognition, connection and a clear ready state, without making port forwarding, dynamic DNS or a second VPN product the central experience.
That is a product decision about who carries the complexity. The connection system can be sophisticated underneath. The person pairing a phone should understand which hub they are joining, whether it is ready, and what will work after the connection is made. Everything else belongs behind that promise.
Make availability useful, not noisy
The interface shows local, remote, offline or reconnecting only when it changes the next action. A track stays the same object regardless of its route. The product should not turn every browse screen into a network dashboard, but it must give a useful answer when playback is delayed, a route changes or a file cannot be reached.
This is where playback behavior becomes product design. Starting immediately, preserving the selected track while a connection is prepared, recovering after a network change and making a genuine failure actionable are all part of the same decision. The user did not ask for a transport protocol. They asked to hear a track from their library.
Build the missing layer
Direct Iroh/QUIC networking did not exist in React Native when the product needed it. Rather than changing the product promise to fit the available wrapper, I built a deliberately small TurboModule and JSI bridge for iOS and Android.
That was not an engineering detour. It came from the product requirement: a paired phone should be able to reach its hub without turning the customer into the maintainer of a networking stack. The technical boundary stays narrow because the product needs dependable connection and playback behavior, not a general-purpose networking SDK disguised as a feature.
Outcome
Tape Music Suite now runs as a desktop hub with iOS and Android companions, sharing one catalogue across all three and reaching each other directly, with no cloud and no third party in between. That is the actual result: a personal library that used to live on one machine now travels with its owner, and stays the same library wherever they open it. The bridge that makes the mobile side of that networking possible is public, released as part of the wider Iroh ecosystem rather than kept as a private dependency, but it is a means to that end, not the end itself.
The product remains active because the difficult work does not finish when the first connection succeeds. Real devices, weak routes, old libraries and daily listening habits are where this direction is tested. This is a current product, so I am still learning from the edges: what should remain invisible, what must be made legible, and where “local-first” risks becoming another word for maintenance. The standard is simple: control only creates value when it does not feel like an extra job.