This document covers building Spotifly from source and contributing to the project.
Spotifly is a Swift/SwiftUI app that integrates with Spotify using the librespot Rust library for OAuth authentication.
This project demonstrates Swift 6.2's C interoperability to call Rust code:
┌─────────────────────┐
│ SwiftUI App │
│ (ContentView) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ SpotifyAuth.swift │
│ (Swift wrapper) │
└──────────┬──────────┘
│ C FFI
┌──────────▼──────────┐
│ SpotiflyRust │
│ (C module map) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ libspotifly_rust │
│ (Rust static lib) │
│ + librespot-oauth │
└─────────────────────┘
- Xcode 26.2+ (Swift 6.2)
- Rust toolchain (install via rustup)
- macOS 26.2+ (or adjust deployment target)
cd rust
./build.shThis compiles the Rust code into a static library at build/rust/lib/libspotifly_rust.a.
Open Spotifly.xcodeproj in Xcode and build (⌘B), or:
xcodebuild -scheme Spotifly -destination 'platform=macOS' buildSpotifly/
├── Spotifly/ # Swift source files
│ ├── SpotiflyApp.swift # App entry point
│ ├── ContentView.swift # Main UI with OAuth button
│ └── SpotifyAuth.swift # Swift wrapper for Rust FFI
├── rust/ # Rust library source
│ ├── Cargo.toml # Rust dependencies
│ ├── src/lib.rs # Rust FFI implementation
│ ├── include/spotifly_rust.h # C header for FFI
│ └── build.sh # Build script
├── build/rust/ # Built Rust artifacts
│ ├── lib/libspotifly_rust.a # Static library
│ └── include/ # Headers + module map
└── Spotifly.xcodeproj # Xcode project
-
Rust Layer (
rust/src/lib.rs):- Uses
librespot-oauthcrate for Spotify OAuth with PKCE - Exposes C-compatible functions (
extern "C") - Manages async Tokio runtime internally
- Uses
-
C Header (
rust/include/spotifly_rust.h):- Declares the C function signatures
- Used by Swift via a module map
-
Swift Wrapper (
Spotifly/SpotifyAuth.swift):- Imports the
SpotiflyRustC module - Provides a Swift-native async API using
@globalActor - Follows Swift 6.2 concurrency best practices
- Imports the
-
SwiftUI (
Spotifly/ContentView.swift):- Uses
@Observablefor state management @MainActorisolated view model- Initiates OAuth flow on button press
- Uses
When you click "Connect with Spotify":
- The Rust library starts a local HTTP server on
http://127.0.0.1:8888 - Opens Spotify's OAuth page in your browser
- After authentication, Spotify redirects to the local server
- The library captures the authorization code and exchanges it for tokens
- Access token is returned to Swift and displayed in the UI
The following settings are configured in the Xcode project:
- Library Search Paths:
$(PROJECT_DIR)/build/rust/lib - Swift Include Paths:
$(PROJECT_DIR)/build/rust/include - Other Linker Flags:
-lspotifly_rust-framework SystemConfiguration-framework Security-framework CoreFoundation
- The app sandbox is enabled, but you may need to disable it or add network entitlements for the OAuth flow to work properly
- Currently builds for macOS only; iOS would require cross-compilation of the Rust library