postcards v2: design options, multi-image gallery, flip-card (Wendekarte) #2
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
v1 is live at https://post.msbls.de and m likes it ("schon ganz gut"). This is the next iteration — all about the card's composition + rendering. The per-recipient
/c/{token}model and unguessable-token scheme stay exactly as-is; don't touch the URL/persistence model beyond what these features need.Mobile-first remains a hard requirement.
Asks (from m, via WhatsApp)
More design options (Gestaltungsmöglichkeiten) — let the sender pick a layout/style when composing. Keep it a small, tasteful set, do not over-spec. A sensible starting set: a couple of clean themes/background styles + the layout choice below. Surface the choice in the compose flow and persist it with the card so the render matches.
Multiple images per card — support more than one image (v1 already accepts multiple uploads server-side via
images/MAX_IMAGES=8; the gap is the render). Provide a gallery / collage layout for multi-image cards, not just a single image. Mobile-friendly (swipeable or grid).Wendekarte (flip card) — m's most specific wish. A real-postcard feel: image on the FRONT, text on the BACK, with a flip interaction (tap/swipe to flip, mobile-friendly). Offer this as one of the layout options. Front = primary image (with the gallery underneath or on flip as fits), back = the message + sender/recipient.
Design guidance
single(v1 behaviour) /gallery(multi-image) /flip(Wendekarte). Keep it extensible.noindexon compose/card pages (as v1).BASE_URLas v1 does).DB / storage
layout(orstyle) column to thepostcardsschema via a new idempotent migration (the app auto-migrates on boot). IMPORTANT — schema ownership: the prod app connects to msupabase as the postgres role via the pooler. When verifying against msupabase, connect as that samepostgresrole (NOT supabase_admin), otherwise new objects get owned by a role the prod app can't write to and the deploy crash-loops (this exact bug hit v1's first deploy). New migrations must be ownable/writable bypostgres.postcard_images(ordered byposition) — reuse it; render all images per the chosen layout.Definition of done
go build/go vet/go testgreen; verify e2e against msupabase as the postgres role, then clean up test data.m is on vacation — async is fine, no rush messaging.
v2 umgesetzt: Layouts (single / gallery / Wendekarte) + Farbwelten
Alles auf meinem Branch, gebaut/getestet und e2e gegen das echte msupabase (als
postgres-Rolle) verifiziert.Was neu ist
Gestaltungswahl im Compose-Flow — der Absender wählt jetzt beim Erstellen:
single(wie v1),gallery,flip(Wendekarte)theme):classic(Sandpapier, Default),sky(Himmel),dusk(Dämmerung)Beide werden mit der Karte gespeichert und beim Rendern berücksichtigt. Auf der Compose-Seite zeigt eine Live-Vorschau die gewählte Farbwelt sofort am Hintergrund.
Die drei Layouts:
rotateY), funktioniert ohne JavaScript und degradiert sauber: wo keine 3D-Transforms unterstützt werden, stehen Vorder-/Rückseite einfach untereinander;prefers-reduced-motionschaltet die Animation ab. Bei mehreren Bildern zeigt die Vorderseite ein dezentes „🖼️ N“-Badge.Technik
migrations/002_layout_theme.sql: idempotenteALTER TABLE ... ADD COLUMN IF NOT EXISTS layout/theme textmit Defaultssingle/classic. ALTER behält den Tabellen-Owner (postgres) — keine neuen Owned-Objects, also kein Wiederholen des v1-Ownership-Crashs. Auto-Migrate beim Boot.NormalizeLayout/NormalizeTheme) → unbekannte/alte Werte fallen sicher auf v1-Verhalten zurück, der Renderer kann nie brechen.[data-theme]+ CSS-Custom-Properties — restrained, nur Paletten-Tausch, nichts Grelles.noindexbleibt; Domain weiterhin ausBASE_URL(nichts hartkodiert). Korrekte Umlaute überall.postcard_images(nachposition) — pro Layout gerendert.Verifikation
go build/go vet/go testgrün;gofmtsauber. Neue Tests: Normalisierung (Unit) + Template-Render pro Layout.postgres-Rolle (genau wie der prod-App-Connect,100.99.98.203:6789): Migration sauber angewandt, Spalten + Defaults bestätigt, je eine Karte pro Layout (2 Bilder, Themesky) compose→persist→render — alle drei korrekt gerendert, Theme honoriert. Testdaten danach wieder gelöscht (DELETE 3, 0 Reste). Bild-Uploads liefen über Local-Storage, das prod-Bucket blieb unberührt.Hinweis für otto-head (Merge/Deploy)
Die Migration wurde beim e2e-Test bereits auf der prod-DB angewandt (Spalten existieren mit sicheren Defaults) — der alte laufende prod-Binary liest sie noch nicht, also kein Effekt auf die Live-App bis zum Redeploy. Merge → Redeploy auf post.msbls.de ist unkritisch.
Commit:
eef40031f5Branch:
mai/hermes/issue-2-postcards-v2✅ v2 merged & live on https://post.msbls.de
Merged commit
eef4003to main (merge6921faa) and deployed.Head review:
go build/vet/testgreen from a clean checkout (new tests added for layout/render). Migration002_layout_theme.sqlis idempotent (ADD COLUMN IF NOT EXISTS, sane defaults) and applied cleanly — worker correctly heeded the schema-ownership note, no crash-loop this time.Verified live e2e: created a
flip(Wendekarte) card with 2 images ontheme=dusk→ renders with flip markup + both images from Supabase Storage, HTTP 200. layout/theme columns present in the DB. Test data cleaned up (m's own cards left untouched).Deploy gotcha noted for the record:
application.redeployrebuilds the Docker image from Dokploy's existing git checkout — it does NOT pull. Useapplication.deployto fetch the latestmainfirst. (Cost me one stale rebuild before I switched.)Not closing — m closes. Next: #3 (Shlink custom URLs) now unblocked, picking it up.