New Druck tab: upload or pick from the library, choose a target size and copy count per image, pan/zoom crop on a locked aspect ratio, and a live preview that renders the same layout the PDF will contain. Sheet controls for paper, margin, gap, bleed, crop marks, dpi and templates.
Klarbild
Verwandelt Screenshots und Fundstücke in saubere, druckfertige Bilder — Rahmen und Shop-Oberflächen entfernen, exakte Fotoformate (30×40 cm etc.), The-Frame-Querformat, für den Cricut freistellen, und automatisch nach Picdrop ausliefern.
Claim: „Screenshot rein, sauberes Bild raus."
Stack
Astro 5 (SSR, Node standalone) + React-Inseln · Postgres · S3 (MinIO) · pg-boss · sharp · grammY (Telegram) · OKLCH-Tokens, kein Tailwind. Deploy: Gitea → Coolify → Hetzner.
Entwicklung
npm install
cp .env.example .env # Werte eintragen
npm run dev
Migrationen und Seeds laufen beim Serverstart automatisch. Erststart-Passwörter über
SEED_TILL_PASSWORD / SEED_LEA_PASSWORD.
Funktionen (Kurzüberblick)
- Modi: Bereinigen (Screenshot säubern/freistellen/formatieren), Umwandeln (ein Bild + Text, z. B. Foto → Ölgemälde), Kombinieren (mehrere Bilder + Text), Neu erzeugen (nur Text).
- Formate: feste cm-/DIN-/Screen-Formate und frei definierbare — Schlüssel
WxH(z. B.25x35) odersticker<N>(sticker5= 5×5 cm). Parsing insrc/lib/format.ts, keine Migration nötig. - Dateiformat: PNG (verlustfrei, Transparenz) oder JPG (klein, Picdrop-freundlich). Global über
settings.output_ext, pro Rezept viarecipes.output_ext, pro Umwandlung im Studio. JPG nur ohne Alpha. - Auslieferung: Picdrop (SFTP/FTPS) + beliebige Zusatzziele; NAS/Backup-Ziele; optionaler
.md-Metadaten-Beileger pro Ziel schaltbar. Nicht-transparente Ergebnisse gehen als JPG an Picdrop. - Bibliothek: Ordner, Farbmarkierungen, Prompt-Anzeige, Vorher/Nachher, Vollbild + „In Fotos sichern".
- Rechte/Datenschutz: Sichtbarkeit (eigene/alle), anonyme Generierungen, private Sessions, NSFW-Gate.
- Telegram-Bot (grammY-Webhook) als vollwertiger Website-Ersatz. API-Token (
Bearer) für/api/*. - Admin: Key/Picdrop/Modelle/Nutzer/Kostendeckel/Presets/Speicherverwaltung, Picdrop-Diagnose.
Datenmodell / Migrationen
Nummerierte SQL in migrations/, beim Start automatisch (kein ORM-Push). Wichtige Spalten:
items.has_alpha, jobs.status (inkl. failed), jobs.finished_at,
settings.output_ext / recipes.output_ext, settings.*_metadata_sidecar, delivery_targets.*.
Stolpersteine & Lösungen (Learnings)
- „Bild bei Picdrop ✓, aber nicht in der Galerie": Fehldiagnose vermeiden — die Dateien lagen die ganze
Zeit korrekt per SFTP in
/POSTER LEA(per Admin → Picdrop → „Ordner anzeigen" verifizierbar). Der eigentliche Grund war die Sortierung in der Picdrop-Weboberfläche, nicht das Format. Unabhängig davon liefern wir nicht-transparente Ergebnisse jetzt als JPG aus (src/lib/delivery.ts,deliverableBuffer): ~25 MB PNG → ~2 MB JPG, schneller und handlicher — plus wählbares Ausgabeformat (output_ext). - „Unbekanntes Format: sticker5": Seed legte ein Rezept mit Formatschlüssel
sticker5an, den der Resolver nicht kannte → jeder Lauf schlug fehl. Lösung: generisches Parsen vonsticker<N>/WxH. - Auftrag trotz Fehler grün:
jobs.statuskannte keinfailed; alle Positionen fehlgeschlagen wurde trotzdemdone. Lösung: Statusfailed, wenndone=0 && failed>0(src/worker.tsmaybeComplete). - Doppelte Datums-/UUID-Namen:
\b-Wortgrenzen greifen nicht an Unterstrichen. Lösung:\bentfernt, Datum/UUID/Hex global ersetzt (src/lib/pipeline.tscleanMotif). - Content-Type bei gemischten PNG/JPG-Ergebnissen:
file.tssnifft jetzt die Magic Bytes. .tmp--Reste auf Picdrop: früher Temp-Rename-Bug;cleanupTmp+ Admin-Knopf „Reste aufräumen".
Status
Reihenfolge und Nachweise siehe CLAUDE.md. Anforderungen im Handover-Paket
(Imagetool-Lea/00..07). Führend: 01-anforderungen.md.