From 2d61abc40c7e5e7e8cde96fb9c9651f9876e331d Mon Sep 17 00:00:00 2001 From: ssmithx Date: Sat, 25 Jul 2026 01:11:42 +0000 Subject: [PATCH] chore: rename project from podpuddle to podsteadr Renames the repo directory and every podpuddle/PODPUDDLE reference across code, config, and docs to podsteadr/PODSTEADR (package names, Docker Compose project/service/volume names, env var names, UI/RSS strings). Existing Docker volume data (uploaded blobs, mediamtx recordings, the server's sqlite DB and its nostr identity key) was migrated to new podsteadr_-prefixed volumes with matching filenames so it isn't orphaned by the rename. --- .env.example | 2 +- README.md | 6 +++--- blossom/config.yml | 2 +- docker-compose.yml | 14 +++++++------- docs/STATUS.md | 26 +++++++++++++------------- frontend/index.html | 2 +- frontend/package-lock.json | 4 ++-- frontend/package.json | 2 +- frontend/src/App.vue | 2 +- frontend/src/lib/api.ts | 2 +- frontend/src/lib/blossom.ts | 2 +- frontend/src/views/LoginView.vue | 2 +- mediamtx/mediamtx.yml | 8 ++++---- scripts/e2e.mjs | 6 +++--- server/package-lock.json | 4 ++-- server/package.json | 2 +- server/src/app.test.ts | 6 +++--- server/src/app.ts | 2 +- server/src/plugins/nostr-auth.ts | 2 +- server/src/services/rss.ts | 2 +- 20 files changed, 49 insertions(+), 49 deletions(-) diff --git a/.env.example b/.env.example index 1f3d808..eda3722 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,7 @@ # Hostname or IP your users will reach this box on (no scheme, no port) PUBLIC_HOST=localhost -# Where the podpuddle UI/API is reachable from browsers +# Where the podsteadr UI/API is reachable from browsers PUBLIC_URL=http://${PUBLIC_HOST}:8095 # Public endpoints handed out for streaming / playback / uploads diff --git a/README.md b/README.md index 7657346..9dd6d40 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# podpuddle +# podsteadr Self-hosted, nostr-native podcast publishing and livestreaming. @@ -26,7 +26,7 @@ Then open http://localhost:8095, log in with a NIP-07 extension, and follow the | Service | Host port | Purpose | |---|---|---| -| podpuddle | 8095 | Web UI + API + RSS feeds | +| podsteadr | 8095 | Web UI + API + RSS feeds | | MediaMTX | 1935 | RTMP ingest (OBS) | | MediaMTX | 8889 (+8189/udp) | WebRTC/WHIP ingest (browser) | | MediaMTX | 8890 | HLS playback | @@ -54,7 +54,7 @@ Tests: `cd server && npm test`. ## Data -Everything lives in named docker volumes: `podpuddle-data` (SQLite, server nostr key, +Everything lives in named docker volumes: `podsteadr-data` (SQLite, server nostr key, covers), `mediamtx-recordings` (stream recordings, 7-day retention), `blossom-data` (media blobs). `docker compose down` keeps them; `down -v` wipes them. diff --git a/blossom/config.yml b/blossom/config.yml index f06520e..9047e76 100644 --- a/blossom/config.yml +++ b/blossom/config.yml @@ -1,4 +1,4 @@ -# blossom-server (v4.x) configuration for podpuddle. +# blossom-server (v4.x) configuration for podsteadr. # Uploads require a signed nostr auth event (BUD-02, kind 24242); # reads are public so podcast apps can fetch enclosures. diff --git a/docker-compose.yml b/docker-compose.yml index cef1a99..3c15256 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,9 +1,9 @@ -name: podpuddle +name: podsteadr services: - podpuddle: + podsteadr: build: . - container_name: podpuddle + container_name: podsteadr restart: unless-stopped ports: - "8095:8095" @@ -21,7 +21,7 @@ services: BLOSSOM_URL_INTERNAL: http://blossom:3000 NOSTR_RELAYS: ${NOSTR_RELAYS:-wss://relay.damus.io,wss://nos.lol,wss://relay.nostr.band} volumes: - - podpuddle-data:/data + - podsteadr-data:/data - mediamtx-recordings:/recordings:ro depends_on: - mediamtx @@ -29,7 +29,7 @@ services: mediamtx: image: bluenviron/mediamtx:1.19.2 - container_name: podpuddle-mediamtx + container_name: podsteadr-mediamtx restart: unless-stopped ports: - "1935:1935" # RTMP ingest @@ -45,7 +45,7 @@ services: blossom: image: ghcr.io/hzrd149/blossom-server:4 - container_name: podpuddle-blossom + container_name: podsteadr-blossom restart: unless-stopped ports: - "8098:3000" @@ -54,6 +54,6 @@ services: - blossom-data:/app/data volumes: - podpuddle-data: + podsteadr-data: mediamtx-recordings: blossom-data: diff --git a/docs/STATUS.md b/docs/STATUS.md index 01cab68..2340024 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -1,4 +1,4 @@ -# podpuddle — project status & handoff +# podsteadr — project status & handoff _Last updated: 2026-07-10. State: **working, verified end-to-end, parked.**_ @@ -18,7 +18,7 @@ fully standalone compose stack today. ## How to resume ```sh -cd ~/podpuddle +cd ~/podsteadr docker compose up -d # data volumes were kept; everything resumes as-is node scripts/e2e.mjs # 14 automated checks against the running stack ``` @@ -26,14 +26,14 @@ node scripts/e2e.mjs # 14 automated checks against the running stack Open http://localhost:8095 and log in with a NIP-07 extension (Alby, nos2x). For a non-localhost box, edit `.env` (`PUBLIC_HOST=…`) and `docker compose up -d --build`. -State that persists in the named volumes: `podpuddle-data` (SQLite DB, the +State that persists in the named volumes: `podsteadr-data` (SQLite DB, the server's nostr key in `config/server-nostr-key`, admin = first pubkey that ever logged in), `blossom-data` (media blobs), `mediamtx-recordings` (stream recordings, 7-day retention). `docker compose down -v` wipes all of it. Note: the automated e2e run left test data behind (an "E2E Test Show" podcast with 2 episodes, test streams, and the e2e identity as **admin**). The e2e -identity's secret key is in `/tmp/podpuddle-e2e-key` (hex). For real use you +identity's secret key is in `/tmp/podsteadr-e2e-key` (hex). For real use you probably want a clean slate: `docker compose down -v && docker compose up -d`, then log in with your own extension first so *your* pubkey becomes admin. @@ -43,9 +43,9 @@ Three containers on one compose network: | Container | Image | Host ports | Role | |---|---|---|---| -| `podpuddle` | built from `Dockerfile` (node:22 + ffmpeg) | 8095 | Fastify API + built Vue UI + RSS feeds | -| `podpuddle-mediamtx` | `bluenviron/mediamtx:1.19.2` | 1935 (RTMP), 8889 (WHIP), 8189/udp (ICE), 8890→8888 (HLS) | ingest + HLS output + recording | -| `podpuddle-blossom` | `ghcr.io/hzrd149/blossom-server:4` (4.4.1) | 8098→3000 | sha256-addressed media blobs | +| `podsteadr` | built from `Dockerfile` (node:22 + ffmpeg) | 8095 | Fastify API + built Vue UI + RSS feeds | +| `podsteadr-mediamtx` | `bluenviron/mediamtx:1.19.2` | 1935 (RTMP), 8889 (WHIP), 8189/udp (ICE), 8890→8888 (HLS) | ingest + HLS output + recording | +| `podsteadr-blossom` | `ghcr.io/hzrd149/blossom-server:4` (4.4.1) | 8098→3000 | sha256-addressed media blobs | Key flows: @@ -55,7 +55,7 @@ Key flows: directly on any API route (scripting). First pubkey to log in becomes admin. - **Episode upload** — browser hashes the file (`crypto.subtle`, ≤2 GB), signs a kind-24242 BUD-02 auth via NIP-07, PUTs **directly to blossom** (file never - transits podpuddle), then registers `{sha256, size, …}` with + transits podsteadr), then registers `{sha256, size, …}` with `POST /api/podcasts/:id/episodes`; server HEAD-verifies the blob before accepting. Enclosure URL = `/.mp4`. - **RSS** — `GET /feeds/:podcastId/feed.xml`, RSS 2.0 + itunes + podcast @@ -68,7 +68,7 @@ Key flows: travels as `?key=` (OBS stream key) or WHIP `Bearer`, is stored only as a sha256 hash, and never appears in viewer URLs. MediaMTX delegates auth to `POST /api/mediamtx/auth` (2xx = allow); reads are public. -- **Status / NIP-53** — podpuddle polls the MediaMTX API (`:9997/v3/paths/list`, +- **Status / NIP-53** — podsteadr polls the MediaMTX API (`:9997/v3/paths/list`, every 3 s) and flips `planned → live → ended` (the stock MediaMTX image has no shell, so `runOn*` curl hooks are impossible — polling is deliberate). On each transition it (re)publishes the kind-30311 live event **signed by the server's @@ -76,7 +76,7 @@ Key flows: with the user `p`-tagged as `host`, to the relay list in Settings. 30311 is replaceable, which is why the server key signs rather than the user's. - **Recordings** — MediaMTX records fmp4 segments to the shared volume; - podpuddle mounts it read-only, lists per-stream files, and + podsteadr mounts it read-only, lists per-stream files, and `POST /api/streams/:id/recordings/publish` remuxes (`ffmpeg -c copy +faststart`), uploads to blossom **with the server's key** (the only server-signed upload path), and creates the episode. @@ -112,7 +112,7 @@ frontend/ # Vue 3 + Vite + Tailwind + Pinia admin claim, episode blob verification, feed ETag/304, stream key create/verify/rotate, webhook allow/deny paths, settings admin gating). - `node scripts/e2e.mjs` against the compose stack — **14/14**. -- Live leg (manual, via ffmpeg in the podpuddle container): +- Live leg (manual, via ffmpeg in the podsteadr container): - RTMP publish with the right key → HLS `index.m3u8` 200 (after MediaMTX's `?cookieCheck=1` redirect — use `curl -L`). - Wrong key → connection reset by MediaMTX (webhook denial confirmed live). @@ -139,7 +139,7 @@ frontend/ # Vue 3 + Vite + Tailwind + Pinia streaming/seeking is degraded. Options later: upgrade to the Deno rewrite, or front blossom with nginx. 3. **Split-horizon blossom URL**: browsers use `http://:8098`, but inside - the podpuddle container that address doesn't exist. `BLOSSOM_URL_INTERNAL` + the podsteadr container that address doesn't exist. `BLOSSOM_URL_INTERNAL` (compose sets `http://blossom:3000`) is used server-side whenever the active blossom URL equals the bundled default; feeds always carry the public URL. 4. **Stock MediaMTX image has no shell** — `runOnReady`-style hooks can't run @@ -154,7 +154,7 @@ frontend/ # Vue 3 + Vite + Tailwind + Pinia ## Remaining work - **Archipelago packaging** (the original deployment target, archy repo): - `apps/podpuddle/manifest.yml` + `apps/podpuddle-mediamtx` + `apps/podpuddle-blossom` + `apps/podsteadr/manifest.yml` + `apps/podsteadr-mediamtx` + `apps/podsteadr-blossom` following the `apps/btcpay-server` (dependencies) + `apps/monero-ui` (`container.build` on `/opt/archipelago/docker/...`) patterns; bind volumes under `/var/lib/archipelago/`; add ports **8095, 1935, 8889, 8189/udp, diff --git a/frontend/index.html b/frontend/index.html index d918701..66e5144 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3,7 +3,7 @@ - podpuddle + podsteadr
diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5db668a..eaca711 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,11 +1,11 @@ { - "name": "podpuddle-frontend", + "name": "podsteadr-frontend", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "podpuddle-frontend", + "name": "podsteadr-frontend", "version": "0.1.0", "dependencies": { "hls.js": "^1.6.0", diff --git a/frontend/package.json b/frontend/package.json index 69551be..e659130 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,5 +1,5 @@ { - "name": "podpuddle-frontend", + "name": "podsteadr-frontend", "version": "0.1.0", "private": true, "type": "module", diff --git a/frontend/src/App.vue b/frontend/src/App.vue index a19343f..177ddf7 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -16,7 +16,7 @@ async function logout() {
- podpuddle + podsteadr