Repository navigation
Architecture Overview
A short map of how Bòcan is built, for people who want to read or change the code. The detail is in the main repository; this page tells you where to look.
Bòcan is a native Swift 6 app with strict concurrency. The app target (App/) is thin. Almost all the code is in twelve Swift packages under Modules/, and each package has its own tests.
Modules/<Name>/
├── Package.swift
├── Sources/<Name>/
└── Tests/<Name>Tests/
The Xcode project is generated from project.yml with XcodeGen. Do not edit the .pbxproj file by hand.
| Module | What it contains |
|---|---|
Observability |
Structured logging (AppLogger), the in-process log buffer behind the Log Console, telemetry signposts, MetricKit, log redaction |
Persistence |
The GRDB database, schema migrations, repositories, FTS5 search, reactive ValueObservation streams |
AudioEngine |
The AudioEngine actor, the AVFoundation and FFmpeg decoders, the buffer pump, the DSP chain |
Metadata |
Tag read and write with TagLib, cover-art extraction, the LRC lyrics parser |
Acoustics |
Chromaprint fingerprinting, AcoustID and MusicBrainz lookup |
Library |
The folder scanner, the FSEvents watcher, the conflict resolver, the cover-art cache |
Playback |
The QueuePlayer actor, queue, history, shuffle strategies, gapless and crossfade scheduling, system Now Playing, the sleep timer |
Scrobble |
The Last.fm, ListenBrainz, and Rocksky providers, and the offline scrobble queue |
Subsonic |
The Subsonic, Navidrome, and Airsonic client, capability detection, Keychain credentials |
Podcasts |
Feed refresh, search through Podcast Index and iTunes, subscriptions, episode downloads, Podcasting 2.0 extras |
SyncServer |
Phone Sync: pairing, the trust store, the mutual-TLS HTTP server, manifest and file serving |
UI |
SwiftUI views, view models, the mini player, settings, theming, snapshot tests |
No module imports a module above it. Observability is at the bottom and every other module uses it. UI is at the top, and the app target is above UI.
flowchart BT
Observability
Persistence --> Observability
AudioEngine --> Observability
Metadata --> Observability
Acoustics --> Observability
Library --> Persistence
Library --> Metadata
Library --> Acoustics
Playback --> Persistence
Playback --> AudioEngine
Scrobble --> Playback
Subsonic --> Persistence
Podcasts --> Persistence
SyncServer --> Library
SyncServer --> Podcasts
SyncServer --> AudioEngine
UI --> Library
UI --> Playback
UI --> Scrobble
UI --> Subsonic
App --> UI
App --> Podcasts
App --> SyncServer
The diagram shows the main edges only. The exact list is in the Package.swift file of each module.
| Dependency | Used for |
|---|---|
| GRDB | SQLite access, migrations, observation |
| FFmpeg (LGPL-only build, bundled) | Decoding of the formats AVFoundation does not handle, and all network streams |
| TagLib | Tag read and write |
Chromaprint (fpcalc) |
Audio fingerprints for AcoustID |
| FeedKit | RSS and Atom feed parsing |
| SwiftSonic | The Subsonic API client |
| Sparkle 2 | In-app updates |
The full list with licences is in NOTICES.md.
| Dimension | Decision |
|---|---|
| Minimum macOS | macOS 15. Development needs Xcode 27, but the built app runs on macOS 15 and later. |
| Architecture | arm64 only. The bundled FFmpeg libraries and fpcalc come from arm64 Homebrew. |
| Intel (x86_64) | Not supported |
| Document | What it is |
|---|---|
| Design docs index | The architecture decision records (ADRs), numbered in dependency order. Each one covers one subsystem or feature slice: goals, contracts, test plan, acceptance criteria. |
_standards.md |
The engineering rules that bind all code |
GOTCHAS.md |
Traps that each cost a debugging session: the symptom, the rule, the cause, and the file to look at |
data-dictionary.md |
The database schema, generated from a freshly migrated database |
CLAUDE.md files |
Conventions for the repository root, App/, and several modules. They are written for a coding assistant but are plain markdown. |
Some ADRs to start with:
| Topic | ADR |
|---|---|
| Audio engine | ADR-002, ADR-006 (queue and gapless), ADR-095 (crossfade) |
| Persistence | ADR-003 |
| Library scanning | ADR-004 |
| Subsonic | ADR-035 |
| Podcasts | ADR-037 (read this one first) |
| Phone Sync | ADR-060 |
| CI and releases | ADR-033 |
| End-to-end tests | ADR-079 |
bocan.app · Source · Report an issue · Releases · Apache 2.0
Features
- Overview
- Playback and Sound
- Formats
- Library
- Browsing and Playlists
- Interface
- Sources and Sync
- Privacy and Engineering
User Guide
In-App Help
- Getting Started
- Podcasts
- Internet Radio
- Subsonic Servers
- Keyboard Shortcuts
- Mouse Buttons
- Supported Formats
Developer Documentation
Design Notes
Links