- Gleam 38.5%
- Go 34.9%
- Python 11.5%
- JavaScript 8.3%
- CSS 3.3%
- Other 3.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| anywhere | ||
| apps | ||
| docs | ||
| nix | ||
| shared | ||
| .envrc | ||
| .gitignore | ||
| flake.lock | ||
| flake.nix | ||
| justfile | ||
| notater.org | ||
| README.md | ||
| script.sh | ||
Anywhere
A framework for self-hostable personal-cloud apps where the bandwidth-heavy work stays on the user's own hardware. A small broker service negotiates connections between browsers and proxies; the proxy runs whatever app-specific code it likes (downloading from YouTube, peer-fetching from Soulseek, …).
App data flows direct browser ↔ proxy over a WebRTC data channel. The broker is on the path only during connection setup and for HTTP control operations (invite redemption, subscription pushes, encrypted-blob storage). The proxy needs no domain name, no TLS certificate, no port forwarding, no VPN — its single outbound WebSocket to the broker is the only network connection it requires.
┌──────────────┐ HTTPS / WebSocket ┌──────────────┐
│ Browser │ ─────────────────────▶ │ Anywhere │
│ (per-app UI) │ signaling + blobs │ broker │
└──────┬───────┘ │ (Gleam BEAM) │
│ └──────┬───────┘
│ WebRTC data channel │ outbound WS
│ (after broker negotiates) │
▼ ▼
┌────────────────────────────────────────────────────┐
│ App proxy │
│ (runs on user hardware, │
│ AnyTube = Python+aiortc+yt-dlp, │
│ AnySoul = Go+Soulseek client, │
│ …each app provides its own) │
└────────────────────────────────────────────────────┘
Apps
| App | What it does | Lives in | Status |
|---|---|---|---|
| AnyTube | Self-hosted YouTube frontend: subscribe to channels, watch + cache videos, sync state across devices. | apps/anytube/ |
Working — paired-proxy pairing, RSS polling, faststart MP4 streaming, encrypted user-doc sync. |
| AnySoul | Soulseek client with a Spotify-like "search → add to library" UX. | apps/anysoul/ |
POC — Go library scaffold (slsk/), server handshake works, peer connections + transfers + UI TBD. |
Layout
anywhere/ Gleam + mist + wisp broker (BEAM) — signaling, /v1/blob,
/v1/ice-config, /api/* control plane
apps/
├── anytube/
│ ├── frontend/ Gleam + Lustre browser app for AnyTube
│ └── proxy/ Python + aiortc + yt-dlp (the working YouTube app)
└── anysoul/
└── proxy/ Go + slsk library (POC; frontend TBD)
shared/ Gleam types + JSON codecs (path-dep, app-agnostic)
nix/ NixOS module for deploying the broker + apps
docs/ Design / dev / ops single document — see docs/README.md
Quick start
nix develop # python, gleam, erlang, deno, ffmpeg, go, just
just anytube-frontend-build # compile Lustre → ESM, symlink into anywhere/
just anywhere # terminal 1 — Gleam on :8000
just anytube-proxy # terminal 2 — Python aiortc, dials the broker
# or
just dev # both, prefixed output, Ctrl-C stops both
xdg-open http://localhost:8000
The first proxy run logs an owner bootstrap code to stdout. Paste
it (plus the printed proxy_id) into the AnyTube UI's pair form to
claim ownership.
For the AnySoul POC:
export SOUL_USER=yourname
export SOUL_PASS=yourpass
just anysoul-proxy # connects, logs in, idle event loop
Where to read more
docs/README.md— single design / dev / ops document. Architecture, identity & pairing, encrypted-blob sync, dev recipes, deployment notes, trust model.anywhere/README.md— broker internals: HTTP + WebSocket surface, broker actor design, blob store, TURN.apps/anytube/frontend/README.md— the AnyTube Lustre app: routes, WebRTC + MSE + sync FFI, theme.apps/anytube/proxy/README.md— the AnyTube proxy: data-channel RPC table, schema, downloader / poller.apps/anysoul/proxy/README.md— the AnySoul proxy POC + theslskSoulseek client library.shared/README.md— shared types + JSON codecs; schema versioning notes.
A note on names
The project was originally called MuTube (and the first app, the
YouTube one, was MuTube itself). The framework split out as the
codebase grew toward supporting more apps than YouTube; the umbrella
got renamed to Anywhere, the original app to AnyTube. Various wire-
format strings (mutube/v1/* HKDF infos, mutube-v3: recovery code
prefix, on-disk paths like ~/.local/share/mutube/proxy/,
localStorage keys like mutube_v2_paired_proxies) still carry the old
name because changing them would invalidate existing crypto state or
orphan user data. They'll migrate to anywhere/-prefixed forms in a
coordinated schema bump.