iOS App - Personal Project

One library.
Every source.

A hybrid iOS music player that unifies your Apple Music library, imported files, and server-streamed tracks into a single, seamless collection.

Cassette home screen
Cassette settings screen
Cassette app screenshot
3×
Source types unified into one library
Tracks streamed on demand from a server
100%
Offline - once a track is cached locally

Fragmentation
was the problem.

"Most players split your music across different apps. I wanted one app that made streaming, downloaded tracks, and owned files feel like the same collection - because they are."

Built for
daily use.

I wanted a music player I could actually live with - one that plays my offline library exactly the way I like, streams from my own server when I need it, and never interrupts with an ad mid-song.

Every streaming app trades something: your attention, your data, or your control. Cassette trades none of those. It's an app I use every day, shaped entirely around how I listen to music.

Zero ads, ever
Fully customizable
Offline-first
Built for one person's taste

Built to replace three apps.

Cassette handles local files, Apple Music integration, and server-streamed audio with equal depth - queue management, lyrics, history, playlists, theming, and offline playback all included.

On-Demand Streaming
Search and stream audio from your personal server. Smart recommendation queueing keeps playback continuous without manual input.
Unified Library
Downloaded tracks become first-class library items - same metadata, same playlists, same stable ID as local files.
Offline-First
Tracks are cached locally with full metadata and artwork. Once saved, a track works entirely offline without any re-buffering.
Queue & Playback
Full now-playing screen, mini player, queue management, repeat, shuffle, history, and last-position restore between sessions.
Lyrics & Remote
Live lyrics lookup, lock-screen and remote control support via MediaPlayer APIs, and AirPlay compatibility.
Theming System
Dark and light modes with accent-aware color tokens. The entire visual system responds consistently across every screen.

Five layers,
one product.

Each domain has a dedicated manager - playback, library, streaming, theming, settings - wired together at launch. Clean separation means each layer can evolve independently.

SwiftUI Interface
Custom tab shell, floating controls, animated now-playing overlay
UI Layer
Audio Engine
AVPlayer playback, queue state, remote controls, session restore
Playback
Library Manager
Source unification, metadata parsing, stable track IDs
Data
Stream Manager
Search, stream resolution, recommendations, offline caching
Integration
Node.js Service
Remote stream delivery, server-side caching, range-request downloads
Backend

Two sources,
one library.

Cassette unifies two distinct playback sources into a single seamless experience. Whether a track lives on a server or is stored locally on the device, it plays and feels exactly the same.

01
Server
Tracks are streamed from a companion backend server with caching and range-request support for smooth, uninterrupted playback.
02
Local Songs
Tracks stored directly on the device - imported files or previously cached songs - play fully offline with no network dependency.
Playback Source Flow
Server Streaming
Local Songs Offline
One unified library - AVPlayer plays

Technologies
used.

iOS-native from the ground up. A companion Node.js service handles the parts that benefit from running server-side.

iOS / Frontend
SwiftUI
Declarative UI, custom layouts
AVFoundation
Audio session, playback engine
MediaPlayer APIs
Lock screen, remote controls
MusicKit
Apple Music library access
Backend / APIs
Node.js + TypeScript
Media delivery service, cached downloads
Media Streaming API
Primary stream resolution
WebSocket
Real-time delivery endpoint