- Add LocalPlaylistRepository for managing local playlists as M3U8 files - Add LocalPlaylistViewModel for local playlist UI state management - Add LocalPlaylistCard component for displaying local playlists - Update LibraryPlaylistsScreen to show both Spotify and local playlists - Add string resources for local playlist section headers - Register LocalPlaylistRepository and LocalPlaylistViewModel in DI Local playlists are stored as M3U8 files in the Playlists directory, can contain local tracks (from LocalMediaTrack) and are fully integrated with the existing library UI. |
||
|---|---|---|
| .github | ||
| .opencode | ||
| .vscode | ||
| assets | ||
| buildSrc | ||
| composeApp | ||
| gradle | ||
| iosApp | ||
| js_plugin_example | ||
| metadata | ||
| packaging | ||
| plugin_interfaces | ||
| .dockerignore | ||
| .gitignore | ||
| .gitmodules | ||
| .mcp.json | ||
| AGENTS.md | ||
| build.gradle.kts | ||
| CHANGELOG.md | ||
| cliff.toml | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTION.md | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| lefthook.yaml | ||
| LICENSE | ||
| PRIVACY_POLICY.md | ||
| README.md | ||
| settings.gradle.kts | ||
A cross-platform extensible open-source music streaming platform.
Bring your own music metadata/playlist/audio-source with plugins created by community or by
yourself. A small step towards the decentralized music streaming era!
****
🌃 Features
- 🧩 Plugin powered, supports any platform or custom music service through plugins.
- 🗺️ Community driven plugins for popular platforms or create your own.
- ⬇️ Freely downloadable tracks with tagged metadata.
- 🖥️ 📱 Cross-platform support.
- 🪶 Small size & less data usage.
- 🕒 Time synced lyrics regardless of the plugin support.
- ✋ No telemetry, diagnostics or user data collection.
- 🚀 Native performance.
- 📖 Open source/libre software.
- 🔉 Playback control is done locally, not on the server.
⬇️ Download
Download Spotube from the Official Website: https://spotube.cc
🔄 Nightly Builds
Grab the latest nightly builds of Spotube from the Offical Website.
🕳️ Building from source [Click to expand]
Spotube is a Compose Multiplatform app.
1. Prerequisites
-
JDK 21 to run Gradle (the Gradle daemon JDK and GraalVM are provisioned automatically).
-
Rust (
rustup+cargo), for thecomposeApplibrary built through Gobley. -
Android SDK, only for Android builds.
-
ComposeNativeWebview, which isn't on Maven Central yet. Clone it at the commit pinned as
COMPOSE_WEBVIEW_COMMITinspotube-release-binary.ymland run./gradlew publishToMavenLocalin it. -
Linux only: runtime libraries, including VLC. Needed to run the app, including
:composeApp:run:Distro Command Debian/Ubuntu sudo apt-get install libvlc5 vlc-plugin-base libwebkit2gtk-4.1-0 libgtk-3-0 libasound2 libgl1 libxtst6 libxi6 libxrender1Fedora sudo dnf install vlc-libs webkit2gtk4.1 gtk3 alsa-lib mesa-libGL libXtst libXi libXrender(vlc-libsneeds RPM Fusion)Arch / CachyOS / Manjaro sudo pacman -S vlc webkit2gtk-4.1 gtk3 alsa-lib libglvnd libxtst libxi libxrenderopenSUSE sudo zypper install libvlc5 libwebkit2gtk-4_1-0 libgtk-3-0 libasound2 Mesa-libGL1 libXtst6 libXi6 libXrender1On Ubuntu 24.04+/Debian 13,
libgtk-3-0andlibasound2arelibgtk-3-0t64andlibasound2t64; apt resolves this itself.
2. Run in development
Desktop (JVM), fastest edit/run loop
./gradlew :composeApp:run
Android debug APK
./gradlew :composeApp:assembleStableDebug
Use
./gradlew :composeApp:assembleNightlyDebugfor the nightly channel.
Development builds stay fast: the release-only optimizations below are skipped.
3. Build the desktop app
A native build takes about 10 minutes, uses every CPU core and peaks at ~15 GB of RAM.
It only happens for the tasks below, never for run.
Native toolchain (Nucleus downloads GraalVM CE on the first build; set GRAALVM_HOME to use
your own):
| OS | Requirements |
|---|---|
| Linux | gcc, zlib headers, patchelf; rpm for .rpm, fuse + zstd for .AppImage. Debian/Ubuntu: sudo apt-get install build-essential zlib1g-dev patchelf rpm fuse zstd. Fedora: sudo dnf install gcc zlib-devel patchelf rpm-build fuse zstd |
| macOS | Xcode Command Line Tools (xcode-select --install) |
| Windows | Visual Studio Build Tools with "Desktop development with C++" (use an "x64 Native Tools" prompt if native-image can't find MSVC) |
Build and run the app folder:
./gradlew :composeApp:createGraalvmNativeDistributable
Output folder: composeApp/build/compose/binaries/main/graalvm-app/
Build and launch in one step
./gradlew :composeApp:runGraalvmNativeDistributable
Keep the spotube binary next to the libraries it was built with; it loads them from its own
folder.
Installers (each OS builds only its own):
| OS | Command |
|---|---|
| Linux | ./gradlew :composeApp:packageGraalvmDeb :composeApp:packageGraalvmRpm |
| Linux (AppImage) | ./gradlew :composeApp:packageGraalvmAppImage -PappImage=true |
| Windows | ./gradlew :composeApp:packageGraalvmExe (or packageGraalvmMsi) |
| macOS | ./gradlew :composeApp:packageGraalvmDmg |
Output folder:
composeApp/build/compose/binaries/main/graalvm-<format>
Tip
Add
-Pnightly=truefor the nightly channel (separate icons and name).
How the Linux AppImage bundle works
DownloadLinuxGtkBundleTaskdownloads the Ubuntu 24.04 packages (audio-only VLC via vlcj-bundler, GTK 3, WebKitGTK 4.1, glib-networking), keeps only what GTK/WebKit reach and relocates the libraries withpatchelf. Needsar,tar,zstd,readelf,patchelf.- WebKitGTK has its helper-process path compiled in, so
AppImageEnvironmentpatches it to a relative path and moves to that directory at startup. It also setsGIO_EXTRA_MODULESandWEBKIT_DISABLE_DMABUF_RENDERER=1(the bundled WebKitGTK 2.44 never paints against a newer host Mesa). main()must callGraalVmInitializer.initialize()first: the VLC loader and the environment setup readcompose.application.resources.dir.
4. Native build breaks, JVM works
A native image is a closed world: everything reached through reflection, JNI or JNA (vlcj, Zipline,
NewPipe, ktor, datastore, ...) must be declared at build time. Nucleus generates most of it; the
rest lives in composeApp/graalvm/reachability-metadata.json.
Symptoms: ClassNotFoundException, NoSuchMethodException or MissingReflectionRegistrationError
in the native binary, while :composeApp:run works.
./gradlew :composeApp:runWithNativeAgentstarts the app on the JVM with GraalVM's tracing agent.- Use the broken feature, then close the window normally. Ctrl+C discards the recording.
- Commit the updated JSON in
composeApp/graalvm/and rebuild.
Tip
./gradlew :composeApp:runGraalvmNativeis a faster debug loop: a quick-Obbuild that names the missing registration.
Warning
Keep the hand-written
uk.co.caprica.vlcj.binding.lib.LibVlcentry, or playback fails to initialize.
5. Production vs development builds
Production mode turns on automatically for package*, create*, notarize* and
nativeImageCompile tasks. Force it with -Pproduction=true|false.
| Area | Development | Production |
|---|---|---|
| Rust lib | fast debug profile |
release with LTO and stripping (31 MB → 1.8 MB) |
| Desktop app | hot-reloadable JVM app | size-optimized (-Os) GraalVM native image |
| Native libs | all | host OS/CPU only; Skia loaded from lib/; on Linux ~10 KB libjvm.so/libjava.so shims instead of the JDK's 28 MB one |
Android picks the Rust profile from its build type.
6. Releases
Run spotube-release-binary.yml manually
(workflow_dispatch) as stable, beta or nightly.
- Beta: the stable build as a draft, tagged
v<version>-beta.N. SetbetaNumberincomposeApp/build.gradle.ktsto N, and back tonullfor stable. - Desktop: each platform (Linux x86_64 and aarch64, Windows, macOS) builds its installers on its own runner.
- Android: a signed APK.
📚 Resources
Core stack
- Kotlin Multiplatform
- Compose Multiplatform
- Compose Hot Reload
- Koin for KMP
- Ktor client
- DataStore for KMP
Desktop and native
- Nucleus: desktop packaging and GraalVM integration
- ComposeNativeWebview
- GraalVM Native Image and its reachability metadata
- Gobley: Rust in Kotlin Multiplatform
- vlcj: VLC bindings for audio playback
Plugins
- Zipline: runs the JS plugins
👥 The Spotube team
- Kingkor Roy Tirtho - The Founder, Maintainer and Lead Developer
- Owen Connor - The Cool Discord Moderator
- Piotr Rogowski - The MacOS Developer
- Rusty Apple - The Mysterious Unknown Guy
💼 License
Spotube is open source and licensed under the AGPL-3.0-or-later License.

