Files
livef12rocks/SOUL.md
T
Frank Schwenk c03f17488c
CI / lint-and-test (push) Failing after 1m18s
feat: organizer Android app and token-gated upload API
Replace Syncthing as the product upload path with a share-target app
and POST /api/jobs. Web UI live-polls job progress.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-27 21:38:50 +02:00

4.8 KiB

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

- 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)