Skip to content
Rymflux Documentation
Esc
navigateopen⌘Jpreview
On this page

The core app

Yes. In fact, this is a very good use case for this type of architecture. Many media applications use a similar idea because it separates the core application from the content providers.

Here’s how it could work.

The core app

Your music app is responsible for:

  • Searching across plugins
  • Showing albums, artists, and songs
  • Playing audio
  • Managing downloads
  • Caching
  • Playlists
  • User interface

It knows nothing about Spotify, SoundCloud, YouTube, Archive.org, or any future source.

                Music App

      ┌──────────────┼──────────────┐
      │              │              │
   Search        Playback      Downloads

              Plugin Manager

     ┌──────────┬──────────┬──────────┐
     │          │          │
 Plugin A   Plugin B   Plugin C

Each plugin represents one music source

For example,

Spotify Plugin

SoundCloud Plugin

Archive.org Plugin

Local Library Plugin

Jamendo Plugin

Each plugin knows only how to talk to its own service.

For example,

Spotify Plugin

Search


Spotify API


Return songs

while

SoundCloud Plugin

Search



SoundCloud API



Return songs

The main app doesn’t care how they work internally.


They all implement the same interface

Instead of a socket API like Herdr, you could define a small JSON protocol.

For example, every plugin supports commands like

search

get_album

get_artist

get_track

stream

download

lyrics

recommendations

So when your app wants to search,

App



search("Imagine Dragons")



Plugin



Returns JSON

Example response

{
  "tracks": [
    {
      "id": "123",
      "title": "Believer",
      "artist": "Imagine Dragons",
      "duration": 204,
      "streamable": true
    }
  ]
}

Every plugin returns the same structure.


Streaming

Suppose the user presses Play.

User



Music App



Spotify Plugin



Returns stream URL or audio stream



Music Player

The player never talks directly to Spotify.


Downloading

Likewise,

Download



Plugin



Downloads file



Returns path



Music library

or

Plugin



Returns download URL



Main app downloads

Both designs work.


Adding new music sources

Imagine six months later someone builds a plugin for Bandcamp.

Nothing changes in your app.

Before

Spotify

SoundCloud

Archive.org


Later

Spotify

SoundCloud

Archive.org

Bandcamp

The app discovers the new plugin and starts using it.

No changes to the core application.


Discovery

Just like Herdr,

each plugin could include a manifest.

Example

id = "spotify"

name = "Spotify"

version = "1.0"

author = "John"

entry = "./spotify-plugin"

supports = [
    "search",
    "stream",
    "download",
    "lyrics"
]

Your app scans

plugins/

    spotify/

        plugin.toml

    soundcloud/

        plugin.toml

    archive/

        plugin.toml

Communication

You have several choices.

Option 1: Local socket (like Herdr)

App

⇄ Socket

⇄ Plugin

Works in every language.


Option 2: HTTP

Plugin starts a small local server.

GET /search

GET /album

GET /track

POST /download

Very easy because every language supports HTTP.


Option 3: JSON over stdin/stdout

The app launches the plugin.

App



stdin



Plugin



stdout



App

This is how tools like Git, the Language Server Protocol (LSP), and many command-line integrations communicate.


Why this architecture is attractive

It has several benefits:

  • Extensibility: New music services can be added without changing the core app.
  • Language independence: Plugin authors can use Python, Rust, Go, JavaScript, or any language that can produce an executable.
  • Isolation: If one plugin crashes, the app can often recover without affecting other plugins.
  • Maintainability: Bugs or API changes in one music service are isolated to that plugin.

One important consideration

If your plugins access commercial streaming services (such as Spotify, Apple Music, or YouTube Music), you need to ensure they comply with those services’ APIs, authentication requirements, and terms of service.

Overall architecture

                     Music App

              Plugin Manager

      Reads plugin.toml manifests

      Starts plugin executables

        JSON / Socket / HTTP

      ┌────────┬────────┬────────┐
      │        │        │
 Spotify   SoundCloud   Archive.org
  Plugin      Plugin       Plugin
      │        │            │
      ▼        ▼            ▼
  Service APIs or local media sources

For a music application, I would actually take Herdr’s idea one step further: define a strict plugin API (for search, metadata, streaming, downloading, authentication, etc.) and communicate using JSON-RPC over stdin/stdout or a local socket. This gives you the same language-agnostic flexibility while keeping plugins isolated and easy to develop.

Was this page helpful?