# 07 — Guest PWA Goal - Delight guests with a frictionless, installable photo experience that works offline, respects privacy, and requires no account. Non-Goals (MVP) - No comments or chat. No facial recognition. No public profiles. No videos. Personas - Guest (attendee) — scans QR, uploads photos, browses and likes. - Host (tenant) — optionally shares event PIN with guests; moderates via Tenant Admin PWA. Top Journeys - Join: Scan QR → Open event → Accept terms → Optional PIN → Land on Gallery. - Upload: Add photos → Review → Submit → Background upload → Success/Retry. - Browse: Infinite gallery → Filter (emotion/task) → Open photo → Like/Share → Back. Core Features - Event access - Access token embedded in QR/link (short-lived, event-scoped); optional PIN challenge. - Token refresh if event remains open; server can revoke/close event at any time. - Offline-first - App shell + last N gallery items cached; uploads queued with Background Sync. - Conflict-safe retries; user can pause/cancel queued uploads. - Capture & upload - Choose from camera or library; limit file size; show remaining upload cap. - Client-side resize to sane max (e.g., 2560px longest edge); EXIF stripped client-side if available. - Assign optional emotion/task before submit; default to “Uncategorized”. - Upload screen shows quota cards (Photos, Guests) with traffic-light styling and friendly copy when nearing limits. - When the backend blocks uploads (limit reached, device blocked, gallery expired), surface localized dialogs with actionable hints. - Gallery - Masonry grid, lazy-load, pull-to-refresh; open photo lightbox with swipe. - Like (heart) with optimistic UI; share system sheet (URL to CDN variant). - Filters: emotion, featured, mine (local-only tag for items uploaded from this device). - Public share: host can hand out `https://app.domain/g/\{token\}`; guests see a themed, read-only gallery with per-photo downloads. - Banner on gallery header highlights approaching expiry (D-7/D-1) and offers CTA to upload remaining shots before the deadline. - Safety & abuse controls - Rate limits per device and IP; content-length checks; mime/type sniffing. - Upload moderation state: pending → approved/hidden; show local status. - Notification Center - Header bell opens a drawer that merges upload queue stats with server-driven notifications (photo highlights, major achievements, host broadcasts, upload failure hints, feedback reminders). - Data fetched from `/api/v1/events/\{token\}/notifications` with `X-Device-Id` for per-device read receipts; guests can mark items as read/dismissed and follow CTAs (internal routes or external links). - Pull-to-refresh + background poll every 90s to keep single-day events reactive without WS infrastructure. - When push is available (VAPID keys configured) the drawer surfaces a push toggle, persists subscriptions via `/push-subscriptions`, and the service worker refreshes notifications after every push message. - Operations playbook: see `docs/ops/guest-notification-ops.md` for enabling push, required queues, and cron health checks. - Privacy & legal - First run shows legal links (imprint/privacy); consent for push if enabled. - No PII stored; guest name is optional free text and not required by default. Screens - Splash/Loading: event lookup + token validation; friendly skeleton. - Slug-based deep links are no longer accepted; guests must enter or scan a join token QR. - Terms & PIN: legal links, optional PIN input; remember choice per event. - Gallery: grid of approved photos; toolbar with filter, upload, settings. - Upload Picker: camera/library, selection preview, emotion/task tagging. - Upload Queue: items with progress, retry, remove; background sync toggle. - Photo Lightbox: zoom, like, share; show emotion tags. - Settings Sheet: Gear-Icon im Header oeffnet eine Sheet-Ansicht mit editierbarem Gastnamen, eingebetteten Rechtsdokumenten (inkl. Zurueck-Navigation) und Cache-Leeren; Theme-Umschalter bleibt im Header. Wireframes - See wireframes file at docs/wireframes/guest-pwa.md for low-fidelity layouts and flows. Core Pages (Pflichtseiten) - Landing / Einstieg - Purpose: Entry to event via QR/PIN; lowest friction. - UI: Single input (QR deep link preferred, fallback PIN field) and Join button. - States: invalid/expired token, event closed, offline (allow PIN entry and queue attempt). - Profil-Setup (Name/Avatar) - Purpose: Optional personalisation fuer Likes/Statistiken; Name wird lokal im Browser gespeichert. - UI: Name-Feld mit Sofort-Validierung; Avatar folgt spaeter. - Behavior: Nicht verpflichtend, aber empfohlen; Name kann jederzeit im Settings Sheet angepasst oder geloescht werden. - Startseite (Home/Feed) - Purpose: Central hub; begruesst Gaeste mit ihrem hinterlegten Namen und fuehrt zu den wichtigsten Aktionen. - Header: Eventtitel plus Live-Kennzahlen (online Gaeste, geloeste Aufgaben); hero-card zeigt "Hey \{Name\}!". - Highlights: Drei CTA-Karten fuer Aufgabe ziehen, Direkt-Upload und Galerie sowie ein Button fuer die Upload-Warteschlange. - Content: EmotionPicker und GalleryPreview bilden weiterhin den Einstieg in Spielstimmung und aktuelle Fotos. - Aufgaben-Flow - Aufgaben-Picker: Choose random task or emotion mood. - Aufgaben-Detail (Karte): Task text, emoji tag, estimated duration, suggested group size; actions: take photo, new task (same mood), change mood. - Foto-Interaktion - Kamera/Upload: Capture or pick; progress + success message on completion; background sync. - Galerie/Übersicht: Grid/Feed; filters: Neueste, Beliebt, Meine; Like hearts. - Foto-Detailansicht: Fullscreen; likes/reactions; linked task + (optional) uploader name. - Motivation & Spiel - Achievements/Erfolge: Badges (e.g., Erstes Foto, 5 Aufgaben, Beliebtestes Foto); personal progress. - Optionale Ergänzungen - Slideshow/Präsentationsmodus: Auto-rotating gallery for TV/Beamer with likes/task overlay. - Onboarding: 1–2 “So funktioniert das Spiel” hints the first time. - Event-Abschluss: “Danke fürs Mitmachen”, summary stats, link/QR to online gallery. Technical Notes - Installability: PWA manifest + service worker; prompt A2HS on supported browsers. - Storage: IndexedDB for queue + cache; `CacheStorage` for shell/assets. - Background Sync: use Background Sync API when available; fallback to retry on app open. - Accessibility: large tap targets, high contrast, keyboard support, reduced motion. - i18n: react-i18next with JSON files (`public/lang/\{locale\}/guest.json`); default `de`, fallback `en`; path-based detection (/de/, /en/); RTL not in MVP. Strings for UI (e.g., gallery, upload, tasks) extracted via i18next-scanner; integrate with prefixed routing and middleware. - Media types: Photos only (no videos) — decision locked for MVP and v1. - Realtime model: periodic polling (no WebSockets). Home counters every 10s; gallery delta every 30s with exponential backoff when tab hidden or offline. API Touchpoints - GET `/api/v1/events/\{token\}` — public event metadata (when open) + theme. - GET `/api/v1/events/\{token\}/photos` — paginated gallery (approved only). - POST `/api/v1/events/\{token\}/photos` — signed upload initiation; returns URL + fields. - POST (S3) — direct upload to object storage; then backend finalize call. - POST `/api/v1/photos/\{id\}/like` — idempotent like with device token. - GET `/api/v1/events/\{token\}/notifications` — list guest notifications (requires `X-Device-Id`). - POST `/api/v1/events/\{token\}/notifications/\{notification\}/read|dismiss` — mark/dismiss notification with device identity. - POST `/api/v1/events/\{token\}/push-subscriptions` — register a browser push subscription (requires `X-Device-Id` + VAPID public key). - DELETE `/api/v1/events/\{token\}/push-subscriptions` — revoke a stored push subscription by endpoint. Limits (MVP defaults) - Max uploads per device per event: 50 - Max file size (after client resize): 6 MB per photo - Max resolution: 2560px longest edge per photo Edge Cases - Token expired/invalid → Show “Event closed/invalid link”; link to retry. - No connectivity → Queue actions; show badge; retry policy with backoff. - Storage full → Offer to clear cache or deselect files. - Permission denied (camera/photos) → Explain and offer system shortcut. Decisions - Videos are not supported (capture/upload strictly photos). Appendix: Page-to-Feature Mapping - Landing: Access, validation, join; deep-link handling. - Profile Setup: Local profile persistence; optional avatar assets. - Home: Header, info bar, CTAs, feed preview. - Tasks: Picker (random/emotion), detail card actions. - Capture/Upload: Camera permissions, client resize, queue handling. - Gallery: Filters, pagination, lightbox. - Achievements: Local badges (MVP), server-backed later. - Slideshow (optional): Read-only, auto-advance, idle-safe.