# SOUL.md โ€” Project Character ## Product Name `live.f12.rocks` ## One-Liner Event photo pep pipeline: organizer Android app -> gmic/rembg -> web. Upload a photo at the event, get back weird/fun filtered variants seconds later. ## Vision At an event (f12 meetup/party), the organizer shares a photo into the Android app. The phone converts it to a 2000px JPEG, uploads it, a worker rips the background off, runs it through a random gmic filter/blend chain, and a handful of variants show up on a shared web page almost immediately โ€” guests need no app, no login, no "process the photos later". If a variant is fun, remix it with different filters right there. Finished jobs land on the organizer's phone (gallery + local notification) and stay on the web for everyone with the link. ## Audience Event organizers (upload via the Android app) and attendees on their phones, often on bad venue wifi. Nobody signs up, nobody logs in. Guests with the link see everything; only the organizer's app can upload. ## Tone & Wording - **Voice:** direct, casual, no explaining-the-obvious. It's a fun tool for an event, not enterprise software. - **Formality:** du. Short German labels in the UI (Ansehen, Remix, Download, Varianten, Zwischenschritte, Warteschlange, Fertig). - **Error messages:** say what broke, don't blame the visitor โ€” most errors here are gmic filter flakiness, not user error. - **Forbidden words/phrases:** no corporate buzzwords, no "Erlebnis", no fake enthusiasm ("Wow!", "Amazing!"). Keep it matter-of-fact. ### Wording Examples | Context | Good | Bad | |---------|------|-----| | Success | `Remix erzeugt.` | `Dein Kunstwerk ist fertig! ๐ŸŽ‰` | | Error | `Foreground-Filter fehlgeschlagen: Timeout nach 120s` | `Etwas ist schiefgelaufen.` | | Empty state | `Noch keine Jobs. Foto in der App teilen, dann kurz warten.` | `Hier ist noch nichts los... lade doch was hoch! ๐Ÿ˜Š` | ## Design - **Palette:** dark background (`#14161a`), off-white text, one warm accent color (`#ff5a1f`) for primary actions/links. No gradients. - **Feel:** utilitarian, mobile-first, touch-friendly. Think backstage tool, not a consumer photo app. Deliberately avoids the generic "purple AI gradient + rounded blob" look. ## Non-Goals - No web auth / accounts / login product โ€” anyone with the link **sees** everything, by design. Upload is a separate shared token in the organizer app, not a user account. - No Play Store / FCM / ntfy dependency. Notifications are local Android. - No beamer/projector product built into this repo. - Not a DAM (digital asset manager) โ€” no albums, tagging, search, retention policies. `incoming/`, `variants/`, and `intermediates/` are the whole data model. - No auto-deletion of incoming uploads. Ever. The worker only reads/copies. - No Syncthing container in this compose. A host Syncthing share can still write `incoming/` as a fallback; it is not the product path. ## Infrastructure (project-local) - Workdir on server: `/home/frank/live.f12.rocks` - Data volume: `${DATA_HOST_DIR}` โ€” prod default `/home/frank/sync.schwenk.online/data/livef12`, local override `./data`. Bind-mounted into `worker` and `web` at `/data` (see `compose.yml`). - Layout: - `incoming/` โ€” HTTP upload (and optional Syncthing drop) - `variants/` โ€” `{stem}_original.jpg`, `{stem}_rembg.png`, `{stem}_vN.png` - `intermediates/` โ€” `{stem}_vN_*.png` (incl. `_post_0` โ€ฆ) - `meta/` โ€” status + manifest JSON - `processed.json` - Domain: `live.f12.rocks`, routed via the shared external `traefik` network, TLS via `myresolver` (see `INFRASTRUCTURE.md`). - rembg model cache lives in the named Docker volume `rembg_cache`. - Organizer Android app lives in `android/` (sideload APK). - `UPLOAD_TOKEN` in server `.env` โ€” required for `POST /api/jobs`. ## Project-Specific Rules ```markdown - Never delete or move files under incoming/ from worker code โ€” the upload API (and optional Syncthing) is the writer there. (reason: uploads are the one copy of the original that exists outside a phone's camera roll) - Keep every intermediate image under intermediates/ โ€” don't clean them up automatically. (reason: useful for debugging bad filter picks, disk is cheap compared to re-running gmic) - gmic/rembg subprocess calls always run under `nice` (see NICE_LEVEL) โ€” the worker box needs to stay responsive for other things during an event. (reason: explicit requirement, avoid CPU starvation) - POST /api/jobs is fail-closed: empty UPLOAD_TOKEN disables uploads. The public web UI stays read-only. ``` --- ## Agent Instructions When updating this file: - Keep rules **unambiguous** โ€” formality of tone doesn't matter, clarity does - Include **wording** for user-facing text; colors are optional - When Frรคnky says *"in this project, never X"*, add it here or in `BOUNDARIES.md` (agent proposes which)