Your music.
Your server.
Your files, kept.

Streams your library on Android and the web. Downloads real files you own. Tells you the truth when something breaks.

Good evening Tonight's mix
NightcallKavinsky
Midnight CityM83
RedboneChildish Gambino
Feel Good Inc.Gorillaz
DreamsFleetwood Mac
Queries4 results
Stream warmingbuffered ahead
Instant historysynced
Liked songs218 tracks
Playlist: Late drives32 tracks
Offline12 downloaded
Downloads 12 on this device
NightcallKavinsky · 3:32 · MP3
✓
Midnight CityM83 · 4:03 · MP3
✓
RedboneChildish Gambino · 5:25 · FLAC
✓
Nightcall1:24 / 3:32
▣Home ⚲Search ⚏Library ↗Downloads
✕
Download failed YouTube refused every client · [ERROR_CODE: DEX01]

Everything a music app should do.
Nothing it shouldn't.

One FastAPI server, one React app, your existing storage. No account servers, no telemetry, no one between you and your music.

Stream with real engineering behind it

Range-request serving, a byte-budgeted warm cache that seeks correctly, and prefetch that buffers the next queue track before you tap play. A seek never poisons the cache; a cold start still starts in about a second.

Downloads you own

Real files into your library, tagged and named your way, with resume from staged bytes. They are yours even if this project disappears tomorrow.

0

Accounts stored elsewhere

Your server issues the sessions, your storage holds the library, your Mongo holds the profile.

Tuned by ear

A 10-band equalizer, bass boost, mono and preamp in a shared Web Audio graph, synced to your account. Sleep timer included.


When a download fails,
it says why.

Most apps hand you a spinner and then a shrug. Rheoson classifies the failure, gives it a traceable code, retries what is retryable on its own, and shows the full sentence on tap.

  • One code per failure. Five characters: domain, category, sequence. Report "DEX01" and it traces to the exact line in the source.
  • Retries before advice. A refused transfer retries itself with fresh credentials first. Switching clients is the last resort, not the first reaction.
  • Readable, everywhere. The full message wraps in the pill and the list, and the info control expands it. Nothing truncates the part that tells you what to do.

Running in five minutes.

Termux turns a spare Android phone into the server. A laptop or a Render free instance works too.

# packages
$ pkg install ffmpeg python nodejs git
$ pip install uv

# get the code
$ git clone https://github.com/picklem0b/Rheoson.git
$ cd Rheoson/api

# backend
$ uv sync --extra dev
$ cp .env.example .env
$ uv run uvicorn app.main:socket_app --host 127.0.0.1 --port 8000

# frontend (second session)
$ cd ~/Rheoson/web && npm install
$ npm run dev

# open http://localhost:5173 in the browser
# any Linux, macOS or WSL machine
$ git clone https://github.com/picklem0b/Rheoson.git
$ cd Rheoson

# backend
$ cd api && uv sync --extra dev && cp .env.example .env
$ uv run uvicorn app.main:socket_app --port 8000

# frontend
$ cd ../web && npm install && npm run dev
# render.yaml ships in the repo: backend + web in one blueprint
# 1. fork the repo on GitHub
# 2. Render dashboard: New, Blueprint, pick the fork
# 3. deploy; free tier sleeps after 15 idle minutes
#    first request after sleep takes about 30 s to wake

Hands on the keys.

Play / pauseSpace
Next trackN
Previous trackP
Seek forward 10 s→
Seek back 10 s←
Volume up↑
Volume down↓
Cycle repeatR
Toggle shuffleS
Toggle queueQ
Toggle lyricsL
Fullscreen playerF
MuteM
Focus searchCtrl F