commit 55c0655126c369584efc3f96896fc582de260206 Author: Vuong Hoang Date: Mon Jul 20 10:17:40 2026 -0700 feat(booth): add The Booth — ephemeral media drop board for CC sessions A standing user-level web server (nh3-dev :8090) that renders drop-folders under ~/booth-data as ephemeral media "booths" so Claude Code sessions can surface A/B renders and smoke results to the operator, then let them self-wipe. - Scan-and-serve model, no database, no upload API — a booth is just a folder. A folder's own index.html is served verbatim; otherwise an auto-gallery of images / webm+mp4 video / audio is rendered, with .txt caption sidecars folded in (labels A/B pairs). - 24h TTL from newest mtime in the tree; background sweeper wipes stale booths. - Path-traversal + symlink-escape guarded; delete via UI button or DELETE API. - FastAPI + Jinja2, runs from the checkout under systemctl --user (booth.service), alongside the other nh3-dev fleet sidecars. 15 tests, all green. - Homepage tile added (Apps -> The Booth, siteMonitor /healthz). - Harden the homepage rsync doc: exclude *.bak* and logs/ so --delete can't wipe the host's dated services.yaml backups (footgun found deploying this). diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c845f32 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.venv/ +__pycache__/ +*.pyc +*.egg-info/ +.pytest_cache/ +booth-data/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..24928b2 --- /dev/null +++ b/README.md @@ -0,0 +1,104 @@ +# The Booth + +A dead-simple standing web server for surfacing **ephemeral media** to the +operator — A/B renders, smoke-test screenshots, audio/video samples. A Claude +Code session drops a folder of files somewhere on disk; the Booth renders it as +a browsable "booth" and **wipes it 24h after the last activity**. No database, +no upload API — the filesystem *is* the state. + +- **Live:** http://10.100.10.50:8090/ (nh3-dev) · linked from Homepage → *Apps → The Booth* +- **Data dir:** `~/booth-data/` on nh3-dev (one subfolder per booth) +- **TTL:** 24h, measured from the newest mtime in a booth's tree (it lives while + you're touching it, self-destructs 24h after you stop) + +## How a session posts + +A booth is **just a folder** under the data dir. Three ways, cheapest first: + +```bash +# 1. On nh3-dev — the helper (services/booth/scripts/booth): +booth add my-run out/a.png out/b.png # creates booth + copies, prints URL +booth new my-run # empty booth, then cp/mv into ~/booth-data/my-run/ +booth url my-run # just print the URL +booth ls # list booths +booth rm my-run # wipe now (TTL would anyway) + +# 2. On nh3-dev — raw, no helper: +mkdir -p ~/booth-data/my-run && cp out/*.png ~/booth-data/my-run/ +# -> http://10.100.10.50:8090/b/my-run/ + +# 3. From another host — rsync into the data dir: +rsync -a ./out/ nh3-dev:booth-data/my-run/ +``` + +Then hand the operator `http://10.100.10.50:8090/b/my-run/`. + +## What a booth renders + +- **Has its own `index.html`?** → served **verbatim** (its relative assets — + `chart.png`, `report.css` — resolve out of the same folder). Build whatever + page you want. +- **No `index.html`?** → **auto-gallery** of the folder's media: + - images (`png jpg jpeg gif webp avif svg bmp`) → `` + - video (`webm mp4 ogv m4v mov`) → `