Architecture Overview
Relevant source files
The following files were used as context for generating this wiki page:
Spotty is an experimental, unofficial Spotify Premium client for macOS 15+ on Apple Silicon. It utilizes a multi-tiered Swift architecture for its user interface and application logic while delegating audio streaming, session management, and decoding to a contained Rust-based backend powered by librespot.
Sources: AGENTS.md:3-8, README.md:16-19
The project strictly follows a native macOS design philosophy, using SwiftUI and AppKit for the interface and AVFoundation for audio output. It avoids cross-platform runtimes like WebView or Chromium.
Sources: AGENTS.md:5-7, README.md:16-20
Dependency Structure
The project organizes Swift dependencies in a unidirectional flow to ensure portable domain logic and a thin executable entry point. The composition root assembles production dependencies, while narrow adapters isolate external leaf dependencies.
Sources: AGENTS.md:52-56
This diagram represents the hierarchical relationship between the system's primary modules and external components.
Module Definitions
| Module | Description |
|---|---|
| SpottyApp | The thin executable launcher target. |
| SpottyCore | Application logic coordinating domain policy, UI, and playback. Links SystemConfiguration, Security, CoreFoundation, and AVFoundation. |
| SpottyDomain | Portable domain models and logic, isolated from platform-specific frameworks. |
| SpottyPlaybackCore | A narrow C/Rust adapter providing playback and Spotify Connect capabilities. |
Sources: Package.swift:87-128, AGENTS.md:52-54
Playback and Audio Architecture
Playback utilizes a pinned librespot implementation in Rust. Decoded PCM data crosses a narrow C-based adapter to reach the macOS AVFoundation framework for final audio output.
Sources: AGENTS.md:52-54, 71-72, README.md:16-19
This flowchart illustrates the path of audio data from the Spotify service to the macOS hardware.
The C ABI Surface
The bridge between Swift and Rust is defined by a narrow C interface. The file Sources/Spotty/Spotify/PlaybackCore.swift is the sole importer of the SpottyPlaybackCore module, while RustPlaybackEngine.swift acts as the primary caller.
Sources: Sources/SpottyPlaybackCore/AGENTS.md:7-9, Scripts/check.sh:159-160
Playback Engine Packaging (XCFramework)
The Rust playback engine is built as a static library (.a) and packaged into a macOS-specific XCFramework. This artifact includes a provenance manifest to ensure integrity and traceability.
Sources: Backend/spotty-playback/build-xcframework.sh:78-83, 137-160
Provenance Metadata
Every built XCFramework contains a spotty_playback_provenance.json file. You use this to verify the environment and inputs used during the build.
| Field | Description |
|---|---|
engineInputDigest | SHA-256 hash of the engine source inputs. |
librarySHA256 | SHA-256 hash of the compiled static library. |
sourceRevision | The Git commit hash of the engine source. |
librespotRevision | The specific pinned revision of the librespot-core crate. |
Sources: Backend/spotty-playback/build-xcframework.sh:137-160, Backend/spotty-playback/validate-xcframework.sh:122-140
User Interface and State Management
UI components use SwiftUI and AppKit, adhering to native macOS structures and typography. The architecture enforces a strict separation where views render state and invoke narrow actions but do not own dependencies or orchestration.
Sources: Sources/Spotty/Views/AGENTS.md:8-12, 30-33
UI Design Principles
- Quiet Confidence: Native, visually calm, and information-dense.
- Honest State: State representations (loading, empty, error) are mandatory requirements.
- Lifecycle Awareness: Presentation caches are cost-bounded and released with the window lifecycle.
Sources: Sources/Spotty/Views/AGENTS.md:8-33
Verification and Safety
The system uses automated checks to ensure architectural integrity.
- C ABI Validation: Clang parses the
spotty_playback.hheader to ensure exported symbols match the library's static archive exactly. - Unused Export Detection: The check scripts verify that every C export declared in the header is actually consumed by
PlaybackCore.swift. - Dependency Pinning: SwiftPM pins the playback XCFramework via a checksum in
Package.swift.
Sources: Scripts/check.sh:91-110, 159-166, Package.swift:10-13
Verification Flow
This diagram demonstrates the automated validation process for maintaining a narrow and utilized playback bridge.
Sources: Scripts/check.sh:100-110, 163-167