One of the most compelling features that made iTunes special was Home Sharing—the ability to browse and play music from another computer on your home network without any faffing about with accounts, subscriptions, or cloud sync. It just worked. You'd open iTunes on your Mac, see your partner's library appear in the sidebar, and click through to play their music.
That simplicity has been missing from modern music players for years. Most solutions now funnel you toward streaming services or require complex setup. Kanora is going the other way: we're building a distributed library system that brings back that iTunes Home Sharing magic, but properly designed for 2026 and built with service architecture.
The Vision
macOS becomes the host. Your Mac is where you store everything—external drives plugged in, terabytes of lossless audio, your curated library. It's plugged into your HiFi stack, always available, tuned and ready.
iOS becomes the client. Your iPhone and iPad discover that Mac automatically on your home network via Bonjour. The library appears as another source in the sidebar, just like "On This Device". Browse artists, albums, playlists using the same UI you already know. Stream or download tracks to take with you.
Playback options:
- Stream to the client: Download to iOS cache, play locally while you move around the house
- Remote playback: (Future phase) Control what plays through your HiFi speakers from your phone
- Download for offline: Background queue pre-downloads albums so they're ready when you leave home
This is iTunes Home Sharing for the post-streaming era—local, private, device-agnostic, no subscription.
Architecture: Service-Based Discovery & Switching
The design hinges on one core principle: the data layer is pluggable. Views don't know whether they're talking to local Core Data or a remote REST API. They just ask the service layer for artists, albums, and playlists.
How Discovery Works
-
Mac advertises: When Kanora launches on macOS, it registers itself via Bonjour with service type
_kanora._tcp. This includes the host name, IP, and port. -
iOS listens: The iOS app runs a background Bonjour listener that picks up any Kanora services on the home network. Discovered hosts are stored in Core Data—name, IP, port, last-seen timestamp.
-
User picks a library: In the sidebar, you see "On This Device" and "Ben's Mac" and "Studio Mac". Tapping one switches which library you're browsing. A quick health check ensures the host is reachable, then the view hierarchy swaps in the remote data provider.
No authentication, no pairing tokens for MVP. We trust the home network boundary. If you're on WiFi at home, you get access. This can be enhanced later if needed, but the MVP stays simple.
The LibraryServiceProvider Pattern
Instead of views querying Core Data directly, they use an injected service:
protocol LibraryServiceProvider {
func fetchArtists() async throws -> [Artist]
func fetchArtist(id: UUID) async throws -> Artist
func fetchAlbums() async throws -> [Album]
func fetchAlbum(id: UUID) async throws -> Album
func fetchPlaylists() async throws -> [Playlist]
func fetchPlaylist(id: UUID) async throws -> Playlist
}
Two implementations:
- LocalLibraryService: Queries Core Data (existing behavior, just refactored)
- RemoteLibraryService: Makes HTTP requests to the Mac API
When you switch libraries in the sidebar, ServiceContainer swaps which provider is active. Existing views re-render using the new data source. No view code changes needed—the abstraction handles everything.
The Mac's REST API
The Mac runs a simple HTTP server (port 8008 or user-configurable) that exposes endpoints mirroring your Core Data structure:
GET /api/artists→ all artists with metadataGET /api/albums/{id}→ album details with track listGET /api/playlists/{id}→ playlist with tracksGET /api/files/{trackId}/stream→ audio file bytes (supports HTTP 206 range requests)
Responses are plain JSON, designed to deserialize directly into the same Swift models used locally. No transformation layer—just get the JSON, decode it, use it.
This is intentionally boring and stateless. The API doesn't manage sessions or track state. It's a dumb file server that happens to know about your music library.
Streaming & Caching Strategy
When you play a track from the remote library, this happens:
- Check cache: Is the file already downloaded locally?
- Download to cache: If not, fetch from Mac via the
/streamendpoint - Play from cache: Once available (or while downloading), send the file to AVAudioEngine and start playback
- Background queue: After the current track starts, the system queues remaining album/playlist tracks for download at low priority
This download-then-play model builds the foundation for offline listening later. Cached files aren't archived; they're ephemeral session cache for now. But the plumbing is there to evolve into "save for offline" when you're ready.
A new RemoteFileCache service manages this:
- Priority queue (current/next tracks first)
- LRU cleanup (old files removed when storage fills)
- State tracking (pending, downloading, complete, failed)
- Integrates seamlessly with existing
PlaybackService
Why This Approach?
Simplicity first: No complex auth, no pairing dance, no cloud sync delays. Bonjour finds it. You tap it. It works.
Privacy by default: Your music library never leaves your home network. No cloud, no tracking, no ads.
Reuse everything: Existing UI components (ArtistsView, AlbumsView, playlists) work unchanged. Just swap the data source. This keeps the feature maintainable and reduces the risk of introducing bugs in existing browsing.
Service-oriented: Fits perfectly with Kanora's existing architecture. Tests mock the provider; implementation details (Core Data vs HTTP) are invisible to views.
Incremental delivery: We can ship discovery → browsing → streaming → offline download in phases without reworking the foundation each time.
Implementation Roadmap
Phase 1: Discovery & Sidebar (iOS)
- Bonjour listener for
_kanora._tcp - Store discovered hosts in Core Data
- Sidebar picker to switch between libraries
- Health check before connecting
Phase 2: Remote API (macOS)
- REST endpoints for artists, albums, playlists, tracks
- Audio file streaming with range request support
- JSON serialization
Phase 3: Data Layer Abstraction (iOS)
LibraryServiceProviderprotocolLocalLibraryServicerefactored from existing queriesRemoteLibraryServiceHTTP client- ServiceContainer integration
Phase 4: Download & Streaming (iOS)
RemoteFileCacheservice- Download queue with priority
- Background pre-download for albums/playlists
- PlaybackService integration
Each phase ships working features. Phase 1 lets you browse remote libraries (read-only). Phase 4 adds streaming and offline prep.
What's Out of Scope (For Now)
- Authentication: Trusting home network for MVP
- Remote playback control: Telling your Mac what to play comes later
- Offline archival: Download to keep feature is future work
- External network access: Only home network for now
- Multi-user sync: But stateless API means multiple devices can browse simultaneously
Why Now?
Streaming services have optimized for convenience, but they've also optimized for lock-in. Kanora is built on the belief that you should own your music library and be able to access it however you want, wherever you are—without paying per month.
The host/client architecture makes that real. Your Mac becomes the source of truth. Your phone becomes a window into that library. No internet required. No subscription. Just your music, your way.
This is what music software felt like when it trusted the user. Kanora's bringing it back.
Next post in this series: We'll dive into the Bonjour discovery implementation and how iOS finds Mac hosts on the network.