🎧 Open source Spotify client that doesn't require Premium nor uses Electron! Available for both desktop & mobile!
Go to file
Kingkor Roy Tirtho e02c1b73b4 fix(ios): use MobileVLCKit from CocoaPods instead of a git Swift package
Android Studio couldn't build the iOS app: resolving the videolan/vlckit
Swift package fails inside it (Xcode's source control service reports
"Communication with the service was interrupted"), ending in
"Missing package product 'VLCKit'". VLCKit's README only documents
CocoaPods and Carthage anyway.

- Podfile with MobileVLCKit 3.7.5 (iOS-only build, 233 MB instead of the
  922 MB cross-platform VLCKit 4 binary); build iosApp.xcworkspace.
- VlcPlayerEngine ported to the MobileVLCKit 3 API: it has a real
  "ended" state, so the stop bookkeeping and the post-resume seek
  workaround needed for VLCKit 4 are gone. Buffering/ES-added
  notifications keep arriving while playing, so "playing" is reported
  whenever VLC is playing.
- NativePlayerListener.onBuffered removed: MobileVLCKit has no buffering
  progress callback.
- Pods/ is ignored; AGENTS.md notes the pod install + workspace setup.
2026-11-03 17:57:55 +06:00
.github refactor(jam): move the room server to its own repository 2026-10-31 19:01:44 +06:00
.opencode feat(ui): integrate LocalTextStyle for dynamic tinting in player controls and UI components 2026-10-15 13:12:39 +06:00
.vscode Merge branch 'master' into dev 2026-10-26 15:23:11 +06:00
assets chore(assets): refresh screenshots, store graphics and Steam hero 2026-10-30 14:43:47 +06:00
buildSrc feat(packaging): Flathub, AUR, WinGet and Chocolatey publishing 2026-10-23 10:08:29 +06:00
composeApp fix(ios): use MobileVLCKit from CocoaPods instead of a git Swift package 2026-11-03 17:57:55 +06:00
gradle Merge branch 'dev' into fix/desugar-jdk-libs-nio 2026-11-03 13:42:50 +06:00
iosApp fix(ios): use MobileVLCKit from CocoaPods instead of a git Swift package 2026-11-03 17:57:55 +06:00
js_plugin_example refactor: move package name from dev.krtirtho to org.spotube 2026-10-16 15:37:15 +06:00
metadata chore(assets): refresh screenshots, store graphics and Steam hero 2026-10-30 14:43:47 +06:00
packaging fix(flatpak): grant the Wayland socket so the webview doesn't render black 2026-10-30 22:43:39 +06:00
plugin_interfaces chore: remove devil's name 2026-10-30 10:33:11 +06:00
.dockerignore fix: windows SSL Certificate error breaking login #905 (#1474) 2024-05-04 20:10:19 +06:00
.gitignore fix(ios): use MobileVLCKit from CocoaPods instead of a git Swift package 2026-11-03 17:57:55 +06:00
.gitmodules feat: migration to Compose Multiplatform 2026-06-30 17:00:13 +06:00
.mcp.json feat(ui): integrate LocalTextStyle for dynamic tinting in player controls and UI components 2026-10-15 13:12:39 +06:00
AGENTS.md fix(ios): use MobileVLCKit from CocoaPods instead of a git Swift package 2026-11-03 17:57:55 +06:00
build.gradle.kts feat: integrate Nucleus framework for enhanced window management and webview support 2026-08-14 20:40:37 +06:00
CHANGELOG.md chore: remove devil's name 2026-10-30 10:33:11 +06:00
cliff.toml refactor: move package name from dev.krtirtho to org.spotube 2026-10-16 15:37:15 +06:00
CODE_OF_CONDUCT.md Contribution guidelines added 2022-01-19 22:56:12 +06:00
CONTRIBUTION.md chore: update contact information and library version in project files 2026-10-18 19:23:18 +06:00
gradle.properties ci: remove nightly tag movement from release workflow 2026-10-26 18:11:35 +06:00
gradlew feat: update dependencies and configure compose hot reload settings 2026-08-13 22:03:41 +06:00
gradlew.bat feat: migration to Compose Multiplatform 2026-06-30 17:00:13 +06:00
lefthook.yaml chore: update license information to GNU Affero General Public License 2026-07-23 10:05:14 +06:00
LICENSE feat: migration to Compose Multiplatform 2026-06-30 17:00:13 +06:00
PRIVACY_POLICY.md chore: update contact information and library version in project files 2026-10-18 19:23:18 +06:00
README.md docs: improve formatting and clarity in the documentation 2026-10-30 16:10:00 +06:00
settings.gradle.kts fix: add mavenLocal() to plugin and dependency resolution management 2026-08-15 22:01:56 +06:00

Spotube Logo

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!

Visit the website Discord Server

Support me on Patron Buy me a Coffee

HackerNews

Donate to our Open Collective


Spotube Desktop Spotube Mobile

****

🌃 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]


GitHub Workflow Status

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 the composeApp library 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_COMMIT in spotube-release-binary.yml and run ./gradlew publishToMavenLocal in 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 libxrender1
    Fedora sudo dnf install vlc-libs webkit2gtk4.1 gtk3 alsa-lib mesa-libGL libXtst libXi libXrender (vlc-libs needs RPM Fusion)
    Arch / CachyOS / Manjaro sudo pacman -S vlc webkit2gtk-4.1 gtk3 alsa-lib libglvnd libxtst libxi libxrender
    openSUSE sudo zypper install libvlc5 libwebkit2gtk-4_1-0 libgtk-3-0 libasound2 Mesa-libGL1 libXtst6 libXi6 libXrender1

    On Ubuntu 24.04+/Debian 13, libgtk-3-0 and libasound2 are libgtk-3-0t64 and libasound2t64; 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:assembleNightlyDebug for 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=true for the nightly channel (separate icons and name).

How the Linux AppImage bundle works
  • DownloadLinuxGtkBundleTask downloads 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 with patchelf. Needs ar, tar, zstd, readelf, patchelf.
  • WebKitGTK has its helper-process path compiled in, so AppImageEnvironment patches it to a relative path and moves to that directory at startup. It also sets GIO_EXTRA_MODULES and WEBKIT_DISABLE_DMABUF_RENDERER=1 (the bundled WebKitGTK 2.44 never paints against a newer host Mesa).
  • main() must call GraalVmInitializer.initialize() first: the VLC loader and the environment setup read compose.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.

  1. ./gradlew :composeApp:runWithNativeAgent starts the app on the JVM with GraalVM's tracing agent.
  2. Use the broken feature, then close the window normally. Ctrl+C discards the recording.
  3. Commit the updated JSON in composeApp/graalvm/ and rebuild.

Tip

./gradlew :composeApp:runGraalvmNative is a faster debug loop: a quick -Ob build that names the missing registration.

Warning

Keep the hand-written uk.co.caprica.vlcj.binding.lib.LibVlc entry, 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. Set betaNumber in composeApp/build.gradle.kts to N, and back to null for 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

Desktop and native

Plugins

👥 The Spotube team

💼 License

Spotube is open source and licensed under the AGPL-3.0-or-later License.

© Copyright Spotube 2026