postcards: "no specific addressee" / broadcast mode (one card, share with many) #4

Closed
opened 2026-06-15 16:36:13 +00:00 by mAi · 2 comments
Collaborator

What

m wants a postcard that is not bound to a specific recipient — a broadcast/general card with ONE shareable link he can send to many people at once. Verbatim: "Postkarten ohne bestimmten Adressaten, sodass ich mehreren dieselbe Karte schicken kann."

Technically the /c/{token} link is already forwardable to many — but m wants this as an explicit, clear choice in the compose flow so the UX doesn't imply a 1:1 card.

Asks

  • Add an explicit mode toggle when composing, e.g. "an eine Person" vs "zum Teilen / an mehrere".
  • In broadcast mode: drop the addressee notion — don't ask for / don't render a specific recipient name; the card reads as a general greeting meant for sharing.
  • In 1:1 mode: unchanged from today (optional recipient name, unguessable-token privacy default).
  • Persist the mode with the card so rendering matches (no recipient line for broadcast).

Natural combo with #3 (custom URL)

A broadcast card + a custom memorable slug (e.g. post.msbls.de/sardinien2026) is the obvious pairing — one memorable link for everyone. Build the two coherently.

Constraints

  • Mobile-first. German UI + Umlaute. noindex stays.
  • Unguessable-token privacy default still applies to the 1:1 case.
  • Schema: if a column is needed (e.g. audience single|broadcast, or reuse a nullable recipient), add via idempotent migration; verify against msupabase as the postgres role (not supabase_admin) — see #1/#2 schema-ownership note.

Sequencing

Folded into the #3 shift (same worker, same compose/addressee/URL code) — see the worker instruction. Filed separately for the record; otto-head will close out both on merge.

DoD

  • Compose offers "an eine Person" vs "zum Teilen"; broadcast cards render without a specific-recipient framing.
  • Works together with the custom slug from #3.
  • build/vet/test green; e2e verified; test data cleaned. Commit references #4 (and #3).
## What m wants a postcard that is **not bound to a specific recipient** — a broadcast/general card with ONE shareable link he can send to many people at once. Verbatim: "Postkarten ohne bestimmten Adressaten, sodass ich mehreren dieselbe Karte schicken kann." Technically the `/c/{token}` link is already forwardable to many — but m wants this as an **explicit, clear choice** in the compose flow so the UX doesn't imply a 1:1 card. ## Asks - Add an explicit mode toggle when composing, e.g. **"an eine Person"** vs **"zum Teilen / an mehrere"**. - In broadcast mode: drop the addressee notion — don't ask for / don't render a specific recipient name; the card reads as a general greeting meant for sharing. - In 1:1 mode: unchanged from today (optional recipient name, unguessable-token privacy default). - Persist the mode with the card so rendering matches (no recipient line for broadcast). ## Natural combo with #3 (custom URL) A broadcast card + a custom memorable slug (e.g. `post.msbls.de/sardinien2026`) is the obvious pairing — one memorable link for everyone. Build the two coherently. ## Constraints - Mobile-first. German UI + Umlaute. `noindex` stays. - Unguessable-token privacy default still applies to the 1:1 case. - Schema: if a column is needed (e.g. `audience` single|broadcast, or reuse a nullable recipient), add via idempotent migration; verify against msupabase as the **postgres** role (not supabase_admin) — see #1/#2 schema-ownership note. ## Sequencing Folded into the **#3 shift** (same worker, same compose/addressee/URL code) — see the worker instruction. Filed separately for the record; otto-head will close out both on merge. ## DoD - Compose offers "an eine Person" vs "zum Teilen"; broadcast cards render without a specific-recipient framing. - Works together with the custom slug from #3. - build/vet/test green; e2e verified; test data cleaned. Commit references #4 (and #3).
Author
Collaborator

#4 umgesetzt — Broadcast-Modus („zum Teilen / an mehrere“)

Gemeinsam mit #3 auf demselben Branch gebaut (otto-head-Instruktion).

Was:

  • Expliziter Modus-Toggle im Compose-Flow ganz oben: „An eine Person“ (1:1, wie bisher) vs. „Zum Teilen“ (Broadcast — ein Link für viele, ohne bestimmten Adressaten).
  • Broadcast: kein Adressat. Das Empfänger-Feld wird per JS ausgeblendet, und der Server leert recipient_name serverseitig für Broadcast-Karten (auch ohne JS sicher). Beim Rendern wird keine „Für …“-Zeile gezeigt; das Share-Banner formuliert „Diesen Link kannst du mit allen teilen“.
  • 1:1: unverändert (optionaler Empfängername, Unguessable-Token als Privacy-Default).
  • Modus wird mit der Karte persistiert (audience = single|broadcast, NormalizeAudience normalisiert auf Lesen und Schreiben → alte Zeilen bleiben single).

Kombi mit #3: Broadcast-Karte + Wunsch-Slug = ein merkbarer Link für alle (z. B. post.msbls.de/sardinien2026) — genau m's mentales Modell.

Verifikation: im selben e2e-Lauf wie #3 — Broadcast-Flip-Karte mit Slug: Pretty-URL + „mit allen teilen“-Banner, keine to-line, audience=broadcast gespeichert. Template-Render-Test prüft Broadcast-Banner + dass die Radios bei Prefill korrekt checked sind. build/vet/test/gofmt grün.

Mobile-first, deutsch + Umlaute, noindex bleibt.

Commit: https://mgit.msbls.de/m/postcards/commit/2f0c9b6 (referenziert #3 und #4)
Branch: mai/hermes/issue-3-postcards-custom

## #4 umgesetzt — Broadcast-Modus („zum Teilen / an mehrere“) Gemeinsam mit #3 auf demselben Branch gebaut (otto-head-Instruktion). **Was:** - Expliziter Modus-Toggle im Compose-Flow ganz oben: **„An eine Person“** (1:1, wie bisher) vs. **„Zum Teilen“** (Broadcast — ein Link für viele, ohne bestimmten Adressaten). - Broadcast: kein Adressat. Das Empfänger-Feld wird per JS ausgeblendet, und der Server **leert `recipient_name` serverseitig** für Broadcast-Karten (auch ohne JS sicher). Beim Rendern wird keine „Für …“-Zeile gezeigt; das Share-Banner formuliert „Diesen Link kannst du mit allen teilen“. - 1:1: unverändert (optionaler Empfängername, Unguessable-Token als Privacy-Default). - Modus wird mit der Karte persistiert (`audience` = `single|broadcast`, `NormalizeAudience` normalisiert auf Lesen **und** Schreiben → alte Zeilen bleiben `single`). **Kombi mit #3:** Broadcast-Karte + Wunsch-Slug = **ein merkbarer Link für alle** (z. B. `post.msbls.de/sardinien2026`) — genau m's mentales Modell. **Verifikation:** im selben e2e-Lauf wie #3 — Broadcast-Flip-Karte mit Slug: Pretty-URL + „mit allen teilen“-Banner, **keine** to-line, `audience=broadcast` gespeichert. Template-Render-Test prüft Broadcast-Banner + dass die Radios bei Prefill korrekt `checked` sind. build/vet/test/gofmt grün. Mobile-first, deutsch + Umlaute, `noindex` bleibt. Commit: https://mgit.msbls.de/m/postcards/commit/2f0c9b6 (referenziert #3 und #4) Branch: `mai/hermes/issue-3-postcards-custom`
Author
Collaborator

Live on https://post.msbls.de

Merged in 408b276, deployed. Compose now offers an explicit audience choice (an eine Person / zum Teilen — broadcast); broadcast cards drop the specific-recipient framing. Migration 003 added the audience column (owner-preserving). Verified a broadcast card creates + renders (HTTP 200). Pairs with the #3 custom slug for one memorable shareable link. Not closing — m closes.

## ✅ Live on https://post.msbls.de Merged in `408b276`, deployed. Compose now offers an explicit audience choice (an eine Person / zum Teilen — broadcast); broadcast cards drop the specific-recipient framing. Migration 003 added the `audience` column (owner-preserving). Verified a broadcast card creates + renders (HTTP 200). Pairs with the #3 custom slug for one memorable shareable link. Not closing — m closes.
mAi closed this issue 2026-06-23 15:48:01 +00:00
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: m/postcards#4
No description provided.