added a help system, replaced the words "tenant" and "Pwa" with better alternatives. corrected and implemented cron jobs. prepared going live on a coolify-powered system.

This commit is contained in:
Codex Agent
2025-11-10 16:23:09 +01:00
parent ba9e64dfcb
commit 447a90a742
123 changed files with 6398 additions and 153 deletions

View File

@@ -0,0 +1,93 @@
# Coolify Deployment Guide
Coolify provides a managed Docker host with service orchestration, logs, metrics, CI hooks, and secret management. This document outlines how to run Fotospiel (including the Photobooth FTP stack) on Coolify and how to prepare for SuperAdmin observability.
## 1. Services to deploy
| Service | Notes |
|---------|-------|
| **Laravel App** | Build from this repo. Expose port 8080. Attach environment variables from `.env`. |
| **Scheduler** | Clone the app container; command `php artisan schedule:work`. |
| **Queue workers** | Use `docs/queue-supervisor/queue-worker.sh` scripts (default, media-storage, media-security). |
| **Horizon (optional)** | Add service executing `docs/queue-supervisor/horizon.sh`. |
| **Redis / Database** | Use Coolify managed services or bring your own (RDS/Aurora). |
| **vsftpd container** | Host FTP on port 2121 and mount the shared Photobooth volume. |
| **Photobooth Control Service** | Lightweight API (Go/Node/Laravel Octane) that Coolify can redeploy alongside vsftpd. |
### Volumes
- `storage-app` (Laravel `storage`, uploads, compiled views).
- `photobooth` (shared between vsftpd, control-service, and Laravel).
- Database/Redis volumes if self-hosted.
Mount these volumes in Coolify under “Persistent Storage” for each service.
## 2. Environment & Secrets
Configure the following keys inside Coolifys “Environment Variables” panel:
- All standard Laravel vars (`APP_KEY`, `DB_*`, `QUEUE_CONNECTION`, `AWS_*` etc.).
- Photobooth block (as documented in `.env.example`): `PHOTOBOOTH_CONTROL_*`, `PHOTOBOOTH_FTP_HOST/PORT`, `PHOTOBOOTH_IMPORT_*`.
- New Coolify integration vars (planned for SuperAdmin widgets):
```
COOLIFY_API_BASE_URL=https://coolify.example.com/api/v1
COOLIFY_API_TOKEN=... # generated per project
COOLIFY_SERVICE_IDS={"app":"svc_xxx","ftp":"svc_yyy"}
```
Store the JSON mapping so Laravel knows which Coolify “service” controls the app, queue, vsftpd, etc.
## 3. Deploy steps
1. Add the Git repository to Coolify (build hook). Configure the Dockerfile build args if needed.
2. Define services:
- **App**: HTTP worker (build & run). Health check `/up`.
- **Scheduler**: same image, command `php artisan schedule:work`.
- **Queue**: command `/var/www/html/docs/queue-supervisor/queue-worker.sh default`.
- Additional queue types as separate services.
3. Configure networks so all services share the same internal bridge, allowing Redis/DB connectivity.
4. Attach the `photobooth` volume to both vsftpd and the Laravel app.
5. Run `php artisan migrate --force` from Coolifys “One-off command” console after the first deploy.
6. Seed storage targets if necessary (`php artisan db:seed --class=MediaStorageTargetSeeder --force`).
## 4. Metrics & Controls for SuperAdmin
To surface Coolify data inside the platform:
1. **API Token** create a Coolify PAT with read access to services and optional “actions” scope.
2. **Laravel config** introduce `config/coolify.php` with base URL, token, and service IDs.
3. **Service client** wrap Coolify endpoints:
- `GET /services/{id}` → CPU/RAM, status, last deploy, git SHA.
- `POST /services/{id}/actions/restart` for restart buttons.
- `GET /deployments/{id}/logs` for tailing last deploy logs.
4. **Filament widgets** in SuperAdmin dashboard add:
- **Platform Health**: per service status (App, Queue, Scheduler, vsftpd, Control Service).
- **Recent Deploys**: table of the last Coolify deployments and commit messages.
- **Actions**: buttons (with confirmations) to restart vsftpd or re-run `photobooth:ingest` service.
Ensure all requests are audited (database table) and require SuperAdmin role.
## 5. FTP container controls
Coolify makes it easier to:
- View vsftpd metrics (CPU, memory, network) directly; replicate those values in SuperAdmin via the API.
- Trigger redeploys of the vsftpd service when Photobooth settings change (Laravel can call Coolifys redeploy endpoint).
- Inspect container logs from SuperAdmin by proxying `GET /services/{id}/logs?tail=200`.
## 6. Monitoring & Alerts
- Configure Coolify Webhooks (Deploy succeeded/failed, service unhealthy) → point to a Laravel route, mark incidents in `photobooth_metadata`.
- Use Coolifys built-in notifications (Slack, email) for infrastructure-level alerts; complement with Laravel notifications for application-level events (e.g., ingest failures).
## 7. Production readiness checklist
1. All services built and running in Coolify with health checks.
2. Volumes backed up (database snapshots + `storage` tarball).
3. Photobooth shared volume mounted & writeable by vsftpd + Laravel.
4. Environment variables set (APP_KEY, DB creds, Photobooth block, Coolify API token).
5. Scheduler & queue services logging to Coolify.
6. SuperAdmin Filament widgets wired to Coolify API (optional but recommended).
With this setup you can manage deployments, restarts, and metrics centrally while still using Laravels built-in scheduler and worker scripts. The next step is implementing the `CoolifyClient` + Filament widgets described above.

View File

@@ -2,6 +2,8 @@
This guide describes the recommended, repeatable way to run the Fotospiel platform in Docker for production or high-fidelity staging environments. It pairs a multi-stage build (PHP-FPM + asset pipeline) with a Compose stack that includes Nginx, worker processes, Redis, and MySQL.
> **Coolify users:** see `docs/deployment/coolify.md` for service definitions, secrets, and how to wire the same containers (web, queue, scheduler, vsftpd) inside Coolify. That document builds on the base Docker instructions below.
## 1. Prerequisites
- Docker Engine 24+ and Docker Compose v2.
@@ -106,4 +108,3 @@ Because the app image keeps the authoritative copy of the code, each container r
- Hook into your observability stack (e.g., ship container logs to Loki or ELK).
With the provided configuration you can bootstrap a consistent Docker-based deployment across environments while keeping queue workers, migrations, and asset builds manageable. Adjust service definitions as needed for staging vs. production.

81
docs/help/README.md Normal file
View File

@@ -0,0 +1,81 @@
# Help System Blueprint
This folder defines the bilingual help center that serves both guest app users and customer admins. It stores the source Markdown, translation metadata, and the publishing workflow that feeds the in-app help experiences.
## Goals
- Give each audience (Guests vs. Admins) tailored, task-based documentation in German and English.
- Keep a single Git-tracked source of truth with translation status and review history.
- Deliver lightweight, searchable payloads to both apps (offline capable for guests, richer navigation for admins).
- Allow non-developers to contribute through Filament while still publishing Markdown to the repo.
## Directory Layout
```
docs/help/
├── README.md # This blueprint
├── templates/ # Authoring templates per locale
├── guest/ # Guest-focused articles (paired locales)
│ ├── index.en.md
│ └── index.de.md
└── admin/ # Customer admin articles (paired locales)
├── index.en.md
└── index.de.md
```
- Articles live in the audience folder and follow the naming pattern `<slug>.<locale>.md` (e.g., `offline-sync.en.md`).
- Each article includes YAML front matter to describe metadata used by the app and Filament resource.
## Front Matter Contract
```yaml
title: "Getting Started"
locale: en
slug: getting-started
audience: guest # guest | admin | shared
summary: "Install the guest app and join an event in under a minute."
version_introduced: 2025.4
requires_app_version: "^3.2.0" # optional semver filter for the apps
status: published # draft | review | published
translation_state: aligned # draft | needs_update | aligned
last_reviewed_at: 2025-01-10
owner: cx-team@fotospiel.app # rotational owner or team list
related:
- slug: offline-sync
- slug: privacy-basics
```
- `translation_state` tracks whether the paired locale matches the canonical source. CI should warn when one locale lags.
- `requires_app_version` lets an app hide docs when the installed build lacks that feature.
## Authoring & Translation Workflow
1. **Plan** open an issue referencing the article slug and target locales.
2. **Draft** copy the locale template, write the content, keep paragraphs short for mobile.
3. **Review** tech review (feature owner) + linguistic review (native speaker). Update `status` and `last_reviewed_at`.
4. **Translate** for the paired locale, mark `translation_state` accordingly and link PRs together.
5. **Publish** merge to `main`. A CI job should rebuild the Markdown cache and push structured JSON to storage (e.g., S3 or Redis) consumed by Laravel.
> Tip: prefer screenshots only in admin docs; guest docs focus on concise steps + illustrations already shipped in the app.
## Delivery Architecture
- **Source of truth**: Markdown in this folder.
- **Processing**: an Artisan job (`help:sync`) parses Markdown via `league/commonmark`, validates front matter, generates per-locale JSON bundles, and stores them under `storage/app/help/<audience>/<locale>.json`.
- **API**:
- `GET /api/help?audience=guest&locale=de` → paginated list with `title`, `summary`, `slug`, `version_introduced`, `updated_at`.
- `GET /api/help/{slug}` → full article body + related slugs.
- Guests access anonymously; admins require auth middleware (so we can show restricted docs).
- **Caching**:
- Cache list + article JSON for 10 minutes in Redis; bust cache whenever the sync job runs.
- Guest app prefetches JSON during first online session and stores it in IndexedDB for offline reading.
- Admin app keeps only recent items client-side but relies on online search for canonical versions.
- **Search**:
- During sync, build Lunr/MiniSearch indexes per audience/locale and ship them to the app bundles for offline search.
## Contextual Access
- **Guest App**: add `?` entry points (floating button, settings, upload errors) that deep-link to slugs. Offer article-level language toggles.
- **Admin App / Filament**: show contextual “Need help?” links near complex forms, routing to `/help/{slug}` in an in-app modal. Provide a global Help center route with sidebar nav and server-driven breadcrumbs.
- **Standalone Web**: optional `/help` public site generated from the same Markdown using Vite/React and server-side rendering for SEO.
## Governance & Backlog
- Track work in `docs/todo/help.md` (create if needed) and link issues to article slugs.
- Add CI checks:
- Ensure every `.en.md` file has a matching `.de.md` file with equal `slug`/`version_introduced`.
- Validate required front matter keys.
- Future enhancements:
- Integrate with Paddle customer portal for billing-related admin help.
- Add analytics event (non-PII) for article views through the app to measure usefulness.

View File

@@ -0,0 +1,37 @@
---
title: "Troubleshooting & Incident-Playbooks"
locale: de
slug: admin-issue-resolution
audience: admin
summary: "Leitfäden für typische Admin-Vorfälle von hängenden Uploads bis zu Billing-Sperren."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: reliability@fotospiel.app
related:
- slug: live-ops-control
- slug: privacy-and-support
---
## Upload-Vorfälle
| Symptom | Diagnose | Lösung |
| --- | --- | --- |
| Warteschlange >10Min fest | Live-Ops-Health-Widget prüfen | `php artisan media:backfill-thumbnails --tenant=XYZ` ausführen, Event neu öffnen |
| Einzelner Gast blockiert | Geräte-Limit erreicht | Limit unter Event → Upload-Regeln erhöhen oder Gast bittet Entwürfe zu löschen |
| Fotos ohne EXIF | Gast importiert Screenshots | Kein Fehler; Hinweis geben, dass EXIF optional ist |
## Zugriffsprobleme
- **Admin kommt nicht rein**: Prüfen, ob Einladung akzeptiert wurde; über *Team → Einladung erneut senden* resetten. Bei SSO Pflicht Zuordnung kontrollieren.
- **Gast kann nicht beitreten**: Event-Status muss *Published* sein; direkten Join-Link `https://app.fotospiel.com/join/<code>` teilen.
## Billing & Quoten
- Paddle-Webhook-Fehler sperrt Uploads: `storage/logs/paddle.log` prüfen, Webhook im Paddle-Dashboard erneut senden, anschließend Abo-Status toggeln.
- Speicher zu 90% voll: Archivierung vorziehen oder Add-on im Paddle-Kundenportal buchen.
## Kommunikationsvorlagen
Nutze die vorformulierten Antworten in `docs/content/fotospiel_howto_artikel_detailliert.md`, um Messaging konsistent zu halten.
### Weitere Hilfe
Eskalation an reliability@fotospiel.app mit Event-ID, Kunde und Zeitstempel. Screenshots/Logs anhängen, wenn verfügbar.

View File

@@ -0,0 +1,37 @@
---
title: "Troubleshooting & Issue Resolution"
locale: en
slug: admin-issue-resolution
audience: admin
summary: "Playbooks for the most common admin-side incidents, from stuck uploads to billing locks."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: reliability@fotospiel.app
related:
- slug: live-ops-control
- slug: privacy-and-support
---
## Upload incidents
| Symptom | Diagnosis | Fix |
| --- | --- | --- |
| Queue stuck >10 min | Check Live Ops health widget | Run `php artisan media:backfill-thumbnails --tenant=XYZ` then reopen event |
| Specific guest blocked | Guest reached per-device limit | Increase limit under Event → Upload rules or ask them to clear drafts |
| Photos missing EXIF | Guest imported screenshots | No action; remind them that EXIF is optional |
## Access issues
- **Admin cannot log in**: verify invite accepted; reset via *Team → Resend invite*. Check SSO mapping if enforced.
- **Guest cannot join**: confirm event status is *Published* and share direct join URL `https://app.fotospiel.com/join/<code>`.
## Billing & quotas
- Paddle webhook failure locks uploads: check `storage/logs/paddle.log`, re-send webhook via Paddle dashboard, then toggle the subscription status.
- Storage 90% full: run archive early or purchase add-on via Paddle customer portal.
## Communication templates
Reuse the canned responses under `docs/content/fotospiel_howto_artikel_detailliert.md` to keep messaging consistent.
### Need more help?
Escalate to reliability@fotospiel.app with the event ID, customer account, and timestamp. Attach screenshots/logs when possible.

View File

@@ -0,0 +1,38 @@
---
title: "Checkliste Event-Vorbereitung"
locale: de
slug: event-prep-checklist
audience: admin
summary: "48-Stunden-Countdown, damit Geräte, Gäste und Automationen ready sind, bevor es losgeht."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: ops@fotospiel.app
related:
- slug: live-ops-control
- slug: post-event-wrapup
---
## 4824 Stunden vorher
- [ ] Event in der Admin-App mit korrekter Zeitzone + Aufbewahrungsfrist anlegen.
- [ ] Titelbild (1200×630) hochladen und Übersetzungen für Titel/Beschreibung prüfen.
- [ ] Gästelisten importieren oder QR-Badges erzeugen.
- [ ] Push-Vorlagen testen (Reminder, Achievement-Freischaltung).
## 242 Stunden vorher
- [ ] `tenant:attach-demo-event` im Staging ausführen, um den Ablauf mit dem Team zu proben.
- [ ] Join-QR nahe Eingang und Fotoboxen ausdrucken oder anzeigen.
- [ ] WLAN-SSID/Passwort-Beschilderung vorbereiten.
- [ ] Moderationsregeln mit Kundenvertrag abgleichen (z.B. explizite Inhalte blocken, Freigabe nötig).
- [ ] Paddle/RevenueCat-Status prüfen (alle Ampeln auf Grün).
## Letzte 2 Stunden
- [ ] Demodaten aus dem Live-Event entfernen.
- [ ] Gäste-App auf Testgeräten öffnen und den Schnellstart durchspielen.
- [ ] Live-Ops-Ansicht auf Tablet/Laptop in Bühnennähe starten.
- [ ] Team zu Eskalationswegen briefen (Supportkontakte, Ersatzgeräte, Foto-Guidelines).
### Weitere Hilfe
Siehe `live-ops-control` für Echtzeit-Monitoring oder melde dich bei ops@fotospiel.app.

View File

@@ -0,0 +1,38 @@
---
title: "Event Preparation Checklist"
locale: en
slug: event-prep-checklist
audience: admin
summary: "A 48-hour countdown to ensure devices, guests, and automations are ready before doors open."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: ops@fotospiel.app
related:
- slug: live-ops-control
- slug: post-event-wrapup
---
## 4824 hours before
- [ ] Create the event in the Admin app with correct timezone + retention policy.
- [ ] Upload cover artwork (1200×630) and ensure translations exist for titles/descriptions.
- [ ] Import guest lists or generate QR badges if needed.
- [ ] Test push notification templates (reminders, achievement unlocks).
## 242 hours before
- [ ] Run `tenant:attach-demo-event` in staging to rehearse workflow with staff.
- [ ] Print or display the join QR near entrance and photobooth areas.
- [ ] Prepare onsite Wi-Fi SSID/password signage.
- [ ] Confirm that automatic moderation rules match the client contract (e.g., block explicit content, require approval).
- [ ] Verify Paddle/RevenueCat status dashboards show green.
## Final 2 hours
- [ ] Clear demo data from the live event.
- [ ] Open the guest app on test devices and complete the getting-started flow.
- [ ] Start the Live Ops screen on a tablet/laptop near the stage.
- [ ] Brief staff on escalation paths (support contacts, backup devices, photo guidelines).
### Need more help?
Open `live-ops-control` for real-time monitoring tips or reach out to ops@fotospiel.app.

View File

@@ -0,0 +1,25 @@
---
title: "Hilfecenter für Event-Admins"
locale: de
slug: admin-help-index
audience: admin
summary: "Betriebsleitfäden für Event-Verantwortliche: Onboarding, Setup, Live-Steuerung und Nachbereitung."
version_introduced: 2025.4
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: cx-team@fotospiel.app
related: []
---
Hier findest du alle Informationen, die du als Event-Admin für einen reibungslosen Ablauf brauchst. Die Artikel sind entlang des Event-Lebenszyklus sortiert:
| Phase | Leitfragen | Artikel-Slug |
| --- | --- | --- |
| Konto & Team | Wie lade ich Mitarbeitende ein und setze Branding auf? | `tenant-dashboard-overview` |
| Event-Vorbereitung | Welche Checkliste erledige ich vor Einlass? | `event-prep-checklist` |
| Live-Betrieb | Wie überwache ich Uploads, moderiere Inhalte und sende Hinweise? | `live-ops-control` |
| Abschluss & Compliance | Wie funktionieren Export, Archiv und Datenschutz? | `post-event-wrapup` |
| Troubleshooting | Was tun bei Upload-Problemen, Geräteverlust oder Billing-Fragen? | `admin-issue-resolution` |
Nutze die Navigationsleiste in der Admin-App für den Schnellzugriff oder öffne `/help/admin` im Desktop-Browser für die vollständige Ansicht mit Breadcrumbs und verwandten Artikeln.

View File

@@ -0,0 +1,25 @@
---
title: "Customer Admin Help Center"
locale: en
slug: admin-help-index
audience: admin
summary: "Operational playbooks for event owners: onboarding, event setup, live control, and post-event delivery."
version_introduced: 2025.4
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: cx-team@fotospiel.app
related: []
---
This portal collects everything event admins need to configure customer accounts, run events smoothly, and resolve issues quickly. Articles are grouped by lifecycle:
| Phase | Key Questions | Article Slug |
| --- | --- | --- |
| Account Setup | How do I invite staff and configure branding? | `tenant-dashboard-overview` |
| Event Preparation | What checklists should I complete before doors open? | `event-prep-checklist` |
| Live Operations | How do I monitor uploads, moderate content, and trigger announcements? | `live-ops-control` |
| Wrap-up & Compliance | How are exports, archives, and privacy handled? | `post-event-wrapup` |
| Troubleshooting | How to handle upload issues, device loss, billing, etc. | `admin-issue-resolution` |
Use the navigation sidebar inside the admin app for faster access, or open `/help/admin` in a desktop browser for the full layout with breadcrumbs and related links.

View File

@@ -0,0 +1,39 @@
---
title: "Live-Ops-Steuerung"
locale: de
slug: live-ops-control
audience: admin
summary: "Uploads überwachen, Inhalte moderieren und Durchsagen versenden, während das Event läuft."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: ops@fotospiel.app
related:
- slug: event-prep-checklist
- slug: admin-issue-resolution
---
## Dashboard-Widgets
- **Upload-Durchsatz** Fotos/Minute, farblich markiert bei Rückständen >25.
- **Gerätegesundheit** Top-Geräte mit Fehlern (Berechtigung verweigert, Speicher voll).
- **Moderationswarteschlange** gemeldete Fotos zur Freigabe; Moderator:innen zuweisen.
- **Ankündigungen** Push/Banner erstellen; Sprachversionen möglich.
## Typischer Ablauf
1. Live-Ops-Seite auf Tablet anheften. Auto-Refresh auf 15Sekunden stellen.
2. Durchsatz beobachten, sobald Gäste eintreffen; direkt nach Zeremonien sind >40/min üblich.
3. Wächst der Rückstau, Banner senden („Bitte kurz online bleiben“ oder „Serienaufnahme reduzieren“).
4. Gemeldete Inhalte zügig bearbeiten; Policy verlangt Aktion innerhalb von 10Minuten.
5. *Achievement-Trigger* nutzen, um Badges manuell zu vergeben, falls Automationen ausfallen.
## Eskalationsmatrix
| Problem | Erste Aktion | Eskalation an |
| --- | --- | --- |
| Upload-Warteschlange fest | Health Check ausführen → Event erneut synchronisieren | Reliability Rufbereitschaft |
| Anstößiger Inhalt | Foto ausblenden → Beweis herunterladen → Veranstalter informieren | Legal Duty Officer |
| Billing-Lock | Paddle-Dashboard prüfen → Zahlungsstatus bestätigen | Finance |
### Weitere Hilfe
Siehe `admin-issue-resolution` für detailliertes Troubleshooting oder melde dich im Slack-Channel #ops-help.

View File

@@ -0,0 +1,39 @@
---
title: "Live Ops Control"
locale: en
slug: live-ops-control
audience: admin
summary: "Monitor uploads, moderate content, and push announcements while the event is live."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: ops@fotospiel.app
related:
- slug: event-prep-checklist
- slug: admin-issue-resolution
---
## Dashboard widgets
- **Upload throughput** photos/minute, highlighted when backlog >25.
- **Device health** top devices experiencing errors (permission denied, storage full).
- **Moderation queue** flagged photos awaiting approval; assign to moderators.
- **Announcements** compose push/banner messages; supports locale-specific text.
## Typical workflow
1. Pin the Live Ops page on a tablet. Set auto-refresh to 15 seconds.
2. Watch the throughput graph as doors open; expect spike to 40+/min right after ceremonies.
3. If backlog grows, broadcast a banner reminding guests to stay online or reduce burst uploads.
4. Moderate flagged items quickly; policies require action within 10 minutes.
5. Use the *Achievement trigger* widget to award badges manually if automation criteria fail.
## Escalation matrix
| Issue | First action | Escalate to |
| --- | --- | --- |
| Upload queue stuck | Run health check → re-sync event | Reliability on-call |
| Offensive content | Hide photo → download evidence → notify organizer | Legal duty officer |
| Billing lock | Check Paddle dashboard → confirm payment status | Finance |
### Need more help?
Open `admin-issue-resolution` for detailed troubleshooting or ping #ops-help in Slack.

View File

@@ -0,0 +1,33 @@
---
title: "Nachbereitung & Abschluss"
locale: de
slug: post-event-wrapup
audience: admin
summary: "Highlights exportieren, Daten archivieren und Datenschutzpflichten binnen 72 Stunden erfüllen."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: success@fotospiel.app
related:
- slug: event-prep-checklist
- slug: privacy-and-support
---
## Erste 24 Stunden
- Dankes-Push/E-Mail mit kuratierten Highlights senden (bis zu 40 Fotos auswählen → *Link teilen*).
- Admin-CSV exportieren (Uploads, Likes, Meldungen) für die eigene Ablage.
- Moderationswarteschlange prüfen, damit keine Meldung offen bleibt.
## Innerhalb von 72 Stunden
- Aktion *Archivieren & Bereinigen* starten (Einstellungen → Datenlebenszyklus). Kopiert Medien in Cold Storage und löscht temporäre Caches.
- Gästen Download-Links bereitstellen, falls vertraglich zugesagt.
- Bei eingegangenen DSGVO-Löschanfragen Abschluss bestätigen und Ticket-ID dokumentieren.
## Optionaler Follow-up
- Event als Vorlage duplizieren für zukünftige Produktionen.
- Erkenntnisse oder Verbesserungswünsche in `docs/todo/` festhalten.
### Weitere Hilfe
Wende dich an success@fotospiel.app oder konsultiere die Legal-Pages-Ressource für Compliance-Formulierungen.

View File

@@ -0,0 +1,33 @@
---
title: "Post-Event Wrap-up"
locale: en
slug: post-event-wrapup
audience: admin
summary: "Export highlights, archive data, and fulfill privacy obligations within 72 hours after the event."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: success@fotospiel.app
related:
- slug: event-prep-checklist
- slug: privacy-and-support
---
## First 24 hours
- Send thank-you push/email with curated highlights (select up to 40 photos → *Share link*).
- Export admin CSV (uploads, likes, reports) for your records.
- Review moderation queue to ensure no reports remain unresolved.
## Within 72 hours
- Trigger the *Archive & purge* action (Settings → Data Lifecycle). This copies media to cold storage and deletes transient caches.
- Provide guests with download links if promised in the contract.
- If GDPR deletion requests were filed, confirm completion and record the ticket ID.
## Optional follow-up
- Duplicate the event as a template for future productions.
- Update `docs/todo/` with learnings or improvements for the product team.
### Need more help?
Reach success@fotospiel.app or consult the Legal Pages resource for compliance wording.

View File

@@ -0,0 +1,34 @@
---
title: "Überblick: Kunden-Dashboard"
locale: de
slug: tenant-dashboard-overview
audience: admin
summary: "Mitarbeitende einladen, Branding konfigurieren und globale Kundeneinstellungen verstehen."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: onboarding@fotospiel.app
related:
- slug: event-prep-checklist
- slug: admin-issue-resolution
---
## Wann lesen?
Direkt nach dem Zugriff auf einen neuen Kunden oder wenn neue Mitarbeitende eingearbeitet werden. Das Kunden-Dashboard befindet sich in der Admin-App (Filament) und bietet auf Desktop dieselben Optionen.
## Hauptbereiche
1. **Home** Überblick über laufende Events, Speicherauslastung und offene Meldungen.
2. **Team** Admins per E-Mail einladen, Rollen vergeben (Owner, Manager, Moderator). SSO via Azure AD/Google möglich, falls im Kundenkonto aktiviert.
3. **Branding** Logos hochladen, Akzentfarben wählen, lokalisierten Begrüßungstext für die Gäste-App setzen.
4. **Rechtliches** Impressum/Datenschutz/AGB über die Legal-Ressource pflegen; Änderungen greifen sofort.
5. **Integrationen** Paddle-Keys, RevenueCat-App-IDs, Webhooks und Zapier-Tokens verwalten. Keine Secrets in Dokumente kopieren.
## Best Practices
- Mindestens zwei Owner-Rollen für Redundanz halten.
- Branding oder Automationen zuerst im Staging-Kundenkonto testen.
- Einladungen im Änderungslog (`docs/changes/`) dokumentieren.
### Weitere Hilfe
Siehe `event-prep-checklist` für Event-Vorbereitung oder kontaktiere cx-team@fotospiel.app für Onboarding-Support.

View File

@@ -0,0 +1,34 @@
---
title: "Customer Control Center Overview"
locale: en
slug: tenant-dashboard-overview
audience: admin
summary: "Invite staff, configure branding, and understand how customer-wide settings affect every event."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: onboarding@fotospiel.app
related:
- slug: event-prep-checklist
- slug: admin-issue-resolution
---
## When to read this
Right after receiving access to a new customer account or when onboarding new staff. The Customer Control Center lives in the Admin app (Filament) and mirrors most options on desktop.
## Key areas
1. **Home** snapshot of live events, storage usage, unresolved reports.
2. **Team** invite admins via email, assign roles (Owner, Manager, Moderator). SSO via Azure AD/Google is available if enabled in customer settings.
3. **Branding** upload logos, choose accent colors, set localized welcome text shown in the guest app.
4. **Legal pages** edit Impressum/Privacy/AGB via the Legal resource; changes propagate instantly.
5. **Integrations** manage Paddle keys, RevenueCat app IDs, webhooks, and Zapier tokens. Never paste secrets into articles.
## Best practices
- Keep at least two Owner-level accounts for redundancy.
- Use the staging customer account to test branding or automation before touching production.
- Document invitations in the change log (`docs/changes/`).
### Need more help?
See `event-prep-checklist` for event-level prep or contact cx-team@fotospiel.app for onboarding assistance.

View File

@@ -0,0 +1,36 @@
---
title: "Schnellstart: Event betreten"
locale: de
slug: getting-started
audience: guest
summary: "Fotospiel-App installieren, Event beitreten und die Grundgesten in unter zwei Minuten lernen."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: guest-success@fotospiel.app
related:
- slug: uploading-photos
- slug: offline-sync
---
## Wann lesen?
Du hast einen Event-Code oder QR-Link erhalten und möchtest sofort loslegen. Voraussetzung: aktueller mobiler Browser (Safari, Chrome, Edge, Samsung Internet) und einmalige Online-Verbindung für den Erstabgleich.
## Schritte
1. **Einladungslink öffnen oder QR scannen.** Der Browser zeigt die Startseite der Fotospiel-Gäste-App.
2. **Installation für Vollbild aktivieren.** Tippe auf *Zum Home-Bildschirm* (iOS) bzw. *App installieren* (Android). Optional, aber empfohlen für Offline-Modus und schnellere Uploads.
3. **Event-Code eingeben.** Sechs Zeichen, Groß-/Kleinschreibung egal. Nach QR-Scan wird das Feld automatisch befüllt.
4. **Anzeigenamen wählen.** Dieser erscheint in der Event-Ansicht neben deinen Uploads. Kein Konto oder E-Mail nötig.
5. **Kamera- & Speicherzugriff erlauben.** Wähle „Einmal erlauben“ oder „Beim Verwenden der App“, damit Fotospiel Fotos speichern kann.
6. **Startpaket synchronisieren.** Die App lädt Alben, Achievements und Upload-Regeln herunter. Ein Fortschrittsbalken zeigt den Abschluss für den Offline-Modus.
7. **Gesten entdecken.** Nach oben wischen öffnet die Kamera, links/rechts wechselt das Album, Langdruck auf einem Foto ermöglicht Like oder Meldung.
## Tipps
- Lege die App vor dem Event in die Dock/App-Leiste, damit du sie schnell wiederfindest.
- Teilen sich mehrere Gäste ein Gerät, setze den Anzeigenamen unter Einstellungen → Profil zwischen den Sessions zurück.
- Screenshots verlassen dein Gerät nur, wenn du sie aktiv hochlädst.
### Weitere Hilfe
Siehe `uploading-photos` für Bearbeitungs- und Batch-Uploads oder `privacy-and-support` für Fragen zum Datenschutz.

View File

@@ -0,0 +1,36 @@
---
title: "Quick Start: Join an Event"
locale: en
slug: getting-started
audience: guest
summary: "Install the Fotospiel app, join an event, and learn the core gestures in under two minutes."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: guest-success@fotospiel.app
related:
- slug: uploading-photos
- slug: offline-sync
---
## When to read this
You just received an event code or QR and want to start sharing photos. This guide assumes you have a modern mobile browser (Safari, Chrome, Edge, Samsung Internet) and basic connectivity once for the initial sync.
## Steps
1. **Open the invite link or scan the QR.** The browser launches the Fotospiel guest app landing page.
2. **Install for full-screen mode.** Tap *Add to Home Screen* (iOS) or *Install app* (Android). Installation is optional but unlocks offline mode and faster uploads.
3. **Enter the event code.** Six characters, case-insensitive. If you scanned the QR, the field auto-fills.
4. **Choose a display name.** This appears next to your uploads within the event feed. No account or email needed.
5. **Grant camera & storage permissions.** Select “Allow once” or “Allow while using the app” so Fotospiel can capture and store photos locally.
6. **Sync starter pack.** The app downloads current albums, achievements, and upload rules. A progress bar ensures everything is cached offline.
7. **Explore gestures.** Swipe up to open the camera, left/right to switch album tabs, long-press a photo to like or report.
## Tips
- Pin the app to your dock/home row before the event so you can reopen it instantly.
- If several guests share one device, clear the display name in Settings → Profile between sessions.
- Screenshots never leave your device unless you upload them manually.
### Need more help?
See `uploading-photos` for editing and batch upload tips, or `privacy-and-support` if you have questions about data retention.

View File

@@ -0,0 +1,29 @@
---
title: "Hilfecenter für Gäste"
locale: de
slug: guest-help-index
audience: guest
summary: "Alle Infos für Teilnehmer:innen, um die Fotospiel-Gäste-App zu installieren, einem Event beizutreten und Erinnerungen zu teilen."
version_introduced: 2025.4
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: product-support@fotospiel.app
related: []
---
Willkommen im Hilfebereich für Gäste. Starte mit dem Schnellstart, wenn du Fotospiel zum ersten Mal nutzt. Die Tabelle verlinkt auf alle Leitfäden (jeder Artikel liegt auf Deutsch und Englisch vor).
| Thema | Zweck | Artikel-Slug |
| --- | --- | --- |
| Schnellstart | App installieren, Event-Code eingeben und die wichtigsten Gesten lernen. | `getting-started` |
| Upload-Workflow | Fotos aufnehmen, bearbeiten und mit Hintergrund-Sync hochladen. | `uploading-photos` |
| Offline-Modus & Sync | Teilnehmen auch ohne Netz und sicherstellen, dass nichts verloren geht. | `offline-sync` |
| Datenschutz & Support | Welche Daten gespeichert werden und wie du Hilfe kontaktierst. | `privacy-and-support` |
### So nutzt du die Hilfe
- **Suche**: Verwende die Suche im Hilfebereich oder die Offline-Suche in den App-Einstellungen. Begriffe wie „Upload-Limit“ oder „Link teilen“ funktionieren.
- **Sprache umschalten**: Klick auf das Globus-Symbol innerhalb jedes Artikels, um zwischen DE/EN zu wechseln.
- **Kontext-Links**: Zahlreiche UI-Elemente mit `?`-Symbol führen direkt zum passenden Abschnitt.
Mehr Unterstützung? Tippe in der Gäste-App auf *Kontakt zum Support* (Einstellungen → Hilfe) und nenne deine Event-ID.

View File

@@ -0,0 +1,29 @@
---
title: "Guest Help Center"
locale: en
slug: guest-help-index
audience: guest
summary: "Everything attendees need to install the Fotospiel guest app, join events, and share memories."
version_introduced: 2025.4
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: product-support@fotospiel.app
related: []
---
Welcome to the guest-focused documentation hub. Start with the Quick Start article if this is your first time using Fotospiel. Use the table below to jump to individual guides (each article has both English and German versions).
| Topic | Purpose | Article Slug |
| --- | --- | --- |
| Quick Start | Install the app, join an event, and learn the basic gestures. | `getting-started` |
| Upload Workflow | Capture, edit, and upload photos with background sync. | `uploading-photos` |
| Offline Mode & Sync | Keep participating when connectivity drops and ensure nothing is lost. | `offline-sync` |
| Privacy & Support | Understand what data is stored and how to reach support. | `privacy-and-support` |
### How to use these docs
- **Search**: Use the in-app search bar or offline search in the app settings screen. Keywords like “upload limit” or “share link” are supported.
- **Language toggle**: Switch between EN/DE with the globe icon inside every article.
- **Contextual links**: Many UI screens offer a `?` icon that deep-links directly to the relevant section here.
Need more help? Tap *Contact Support* inside the guest app → Settings → Help. Provide the event ID so we can assist faster.

View File

@@ -0,0 +1,40 @@
---
title: "Offline-Modus & Synchronisierung"
locale: de
slug: offline-sync
audience: guest
summary: "Auch ohne Netz teilnehmen, Uploads sicher zwischenspeichern und den Status prüfen."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: reliability@fotospiel.app
related:
- slug: uploading-photos
- slug: privacy-and-support
---
## Wann lesen?
Du rechnest mit schwacher oder fehlender Verbindung (Gebirge, Keller, Roaming). Sobald die Erst-Synchronisierung abgeschlossen ist, funktioniert die Gäste-App vollständig offline weiter.
## Was bleibt offline verfügbar?
- Event-Feed (die letzten 250 Fotos) und Albumstruktur.
- Upload-Regeln (Größenlimit, Moderationseinstellungen).
- Entwürfe für Achievements und Sticker.
- Auszug des Hilfecenters (Top10 Artikel pro Sprache), sofern du den Hilfebereich mindestens einmal online geöffnet hast.
## Offline-Workflow
1. **Wie gewohnt aufnehmen.** Alles landet verschlüsselt in der lokalen Warteschlange.
2. **Ausstehende Uploads prüfen.** Achte auf das graue Label *In Warteschlange*. Tags/Notizen lassen sich auch offline ergänzen.
3. **Speicher überwachen.** Ein Banner warnt unter 500MB freiem Speicher; lösche gesendete Inhalte oder nutze ein anderes Gerät.
4. **Kurz online gehen.** Sobald irgendein Netz verfügbar ist, Fotospiel öffnen. Die Sync startet automatisch und priorisiert die ältesten Elemente.
5. **Abschluss bestätigen.** Ein grüner Hinweis „Alle Uploads übertragen“ erscheint und der Warteschlangen-Zähler springt auf Null.
## Troubleshooting
- **Bleibt trotz Netz auf „In Warteschlange“?** Flugmodus kurz aktivieren/deaktivieren und App neu öffnen, um den Service Worker zurückzusetzen.
- **Gerätewechsel?** Offline-Warteschlangen verbleiben auf dem ursprünglichen Gerät; kein Abgleich zwischen Geräten.
- **Energiesparmodus** kann Hintergrundsync pausieren. Für große Mengen die App im Vordergrund lassen.
### Weitere Hilfe
Unter Einstellungen → Hilfe → *Diagnosedaten senden* kannst du (sobald du online bist) anonymisierte Logs plus deine Event-ID an den Support schicken.

View File

@@ -0,0 +1,40 @@
---
title: "Offline Mode & Sync"
locale: en
slug: offline-sync
audience: guest
summary: "Participate without coverage, queue uploads safely, and know when everything is delivered."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: reliability@fotospiel.app
related:
- slug: uploading-photos
- slug: privacy-and-support
---
## When to read this
You expect intermittent connectivity (mountains, cellars, roaming). The guest app is built to keep working offline as long as the initial sync completed.
## What stays available offline
- Event feed (latest 250 photos) and album structure.
- Upload rules (size limits, moderation settings).
- Draft achievements and stickers.
- Help center excerpt (top 10 articles per locale) if you opened Help at least once online.
## Offline workflow
1. **Capture as usual.** Everything stores in the encrypted local queue.
2. **Review pending uploads.** Look for the grey *Queued* label. Add tags/notes even while offline.
3. **Monitor storage.** The banner warns if device storage drops below 500MB; delete sent items or transfer to another device.
4. **Reconnect briefly.** Once any network is available, open Fotospiel. Sync restarts automatically, prioritizing oldest items.
5. **Confirm completion.** A green toast “All uploads delivered” appears and the queue counter returns to zero.
## Troubleshooting
- **Stuck in “Queued” despite coverage?** Toggle airplane mode off/on, then reopen the app to reset the service worker.
- **Different devices?** Offline queues stay on the original device; theres no cross-device merge.
- **Battery saver** might pause background sync. Keep the app in the foreground for large batches.
### Need more help?
Use Settings → Help → *Send diagnostics* once you are online; support receives anonymized logs plus your event ID.

View File

@@ -0,0 +1,38 @@
---
title: "Datenschutz & Support"
locale: de
slug: privacy-and-support
audience: guest
summary: "Welche Daten gespeichert werden, wie du Löschungen anstößt und wie du Hilfe erreichst."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: legal@fotospiel.app
related:
- slug: getting-started
- slug: offline-sync
---
## Welche Daten speichern wir?
- **Fotos & Bildunterschriften**: Liegen verschlüsselt im Speicher des Kundenkontos für den vom Veranstalter definierten Zeitraum.
- **Session-ID**: Anonymer Token vom Gerät zur Upload-Nachverfolgung; wird zurückgesetzt, wenn du die App-Daten löscht.
- **Geräte-Metadaten**: Nur Modell + Betriebssystem-Version für Crash-Analysen. Keine Standort-, Kontakt- oder Werbe-IDs.
## Deine Kontrollmöglichkeiten
1. **Einzelne Uploads löschen**: Foto öffnen → `…`*Aus Event entfernen*. Du kannst nur eigene Inhalte löschen.
2. **Lokalen Cache leeren**: Einstellungen → Speicher → *Gerätekopien löschen*. Entfernt Miniaturen und Entwürfe.
3. **Komplette Löschung anfordern**: Einstellungen → Hilfe → *Datenlöschung anfragen*. E-Mail für Bestätigung angeben; wir leiten an den Event-Admin weiter.
## Support-Kanäle
- **In-App**: Einstellungen → Hilfe → *Support kontaktieren*. Optional Screenshot + Diagnosepaket anhängen.
- **E-Mail**: guests@fotospiel.app (Event-Code + Gerät nennen).
- **Vor Ort**: Event-Personal ansprechen; sie eskalieren über die Admin-App.
## Antwortzeiten
- Kritische Probleme (Uploads für gesamtes Event gestört): <15 Minuten.
- Individuelle Lösch- oder Datenschutzanfragen: innerhalb von 48 Stunden.
### Weitere Hilfe
Rechtsseiten (Impressum, Datenschutz, AGB) findest du unter Einstellungen → Rechtliches. Für kundenspezifische Regelungen kontaktiere den Veranstalter direkt.

View File

@@ -0,0 +1,38 @@
---
title: "Privacy & Getting Help"
locale: en
slug: privacy-and-support
audience: guest
summary: "Understand what data is stored, how to request deletions, and how to contact support."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: legal@fotospiel.app
related:
- slug: getting-started
- slug: offline-sync
---
## Data we store
- **Photos & captions**: Stored on the customer accounts encrypted storage for the retention period defined by the event organizer.
- **Session ID**: Anonymous token generated on your device for upload tracking; resets if you clear app storage.
- **Device metadata**: Only model + OS version, used for crash insights. No location, contacts, or advertising IDs.
## Your controls
1. **Delete individual uploads**: Open the photo → tap `…`*Remove from event*. You can delete only your own items.
2. **Erase local cache**: Settings → Storage → *Clear device copies*. This removes cached thumbnails and drafts.
3. **Request full erasure**: Use Settings → Help → *Request data deletion*. Provide email for confirmation; we forward the request to the event admin who controls the customer account.
## Support channels
- **In-app**: Settings → Help → *Contact support*. Includes optional screenshot + diagnostics bundle.
- **Email**: guests@fotospiel.app (mention event code + device model).
- **On-site**: Ask the event staff to escalate via the customer admin app.
## Response times
- Critical issues (uploads failing for entire event): <15 minutes.
- Individual deletion or privacy questions: within 48 hours.
### Need more help?
Review the public legal pages (Impressum, Privacy, AGB) under Settings → Legal, or contact the event organizer directly for customer-specific policies.

View File

@@ -0,0 +1,39 @@
---
title: "Fotos aufnehmen & hochladen"
locale: de
slug: uploading-photos
audience: guest
summary: "Integrierte Kamera nutzen, Aufnahmen bearbeiten und bei Funklöchern auf Hintergrund-Sync setzen."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: guest-success@fotospiel.app
related:
- slug: getting-started
- slug: offline-sync
---
## Wann lesen?
Du bist bereits einem Event beigetreten und möchtest verstehen, wie der Aufnahme-Workflow funktioniert, welche Qualitätsgrenzen gelten und was bei Verbindungsproblemen passiert.
## Schritt für Schritt
1. **Fotospiel-Kamera öffnen.** Vom Feed nach oben wischen oder auf das Auslösersymbol tippen.
2. **Aufnahmemodus wählen.**
- *Einzelfoto*: Standardmodus mit HDR-Anpassung.
- *Serie*: Auslöser halten, bis zu 5 Bilder; die App wählt automatisch das schärfste.
- *Import*: Miniatur antippen, um vorhandene Fotos/Screenshots zu laden.
3. **Anpassungen vornehmen.** Zuschneiden, drehen oder optionalen Text-Sticker hinzufügen. Alles passiert lokal. Mit *Speichern* bestätigen.
4. **Album & Tags setzen.** Ordne das Foto dem passenden Kapitel (z.B. Trauung) zu und füge bei Bedarf Stimmungstags an. Alben sind offline vorhanden.
5. **Upload-Warteschlange prüfen.** Offene Elemente erscheinen im Tab `Uploads` mit Status-Badge: *In Warteschlange*, *Sendet* oder *Erfordert Aktion*.
6. **Hintergrund-Sync abwarten.** Beim Schließen sendet die App noch ca. 30Sekunden (Systemlimit). Später öffnen setzt den Upload automatisch fort.
7. **Fehler beheben.** Warnsymbol tippen → *Jetzt erneut versuchen* oder *Löschen*. Häufige Ursachen: Flugmodus, entzogene Berechtigungen, Speicher voll.
## Tipps
- Fotos übernehmen die Gerätezeit. Unter "Event-Zeit verwenden" kannst du die Metadaten angleichen.
- Markiere bis zu 10 wartende Uploads gleichzeitig zum Löschen oder erneuten Senden.
- Likes und Kommentare synchronisieren getrennt und blockieren den Foto-Upload nicht.
### Weitere Hilfe
Siehe `offline-sync` für längere Offline-Phasen oder kontaktiere den Support unter Einstellungen → Hilfe.

View File

@@ -0,0 +1,39 @@
---
title: "Capture & Upload Photos"
locale: en
slug: uploading-photos
audience: guest
summary: "Use the built-in camera, edit shots, and rely on background sync if connectivity drops."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: aligned
last_reviewed_at: 2025-02-22
owner: guest-success@fotospiel.app
related:
- slug: getting-started
- slug: offline-sync
---
## When to read this
You already joined an event and want to understand the capture workflow, quality limits, and what happens if uploads fail or the connection disappears.
## Step-by-step
1. **Open the Fotospiel camera.** Swipe up from the timeline or tap the shutter icon.
2. **Pick a capture mode.**
- *Single shot*: default mode with HDR tuning.
- *Burst*: hold the shutter to capture up to 5 frames; the app picks the sharpest by default.
- *Import*: tap the gallery thumbnail to select existing photos/screenshots.
3. **Apply adjustments.** Crop, rotate, or add the optional text sticker. All edits happen on-device. Tap *Save* to confirm.
4. **Choose the album & tags.** Assign to the correct chapter (e.g., Ceremony) and optionally add mood tags. Albums are cached offline.
5. **Review upload queue.** Pending items appear in the `Uploads` tab with a status pill: *Queued*, *Sending*, or *Needs attention*.
6. **Let background sync finish.** Closing the app keeps uploads going for ~30 seconds (platform limit). Reopen later to resume automatically.
7. **Fix failed uploads.** Tap the warning icon → *Retry now* or *Delete*. Common issues: airplane mode, revoked permissions, storage full.
## Tips
- Photos inherit the device timestamp; if clocks differ from event time, toggling “Use event time” adjusts metadata.
- Batch-select up to 10 pending uploads to delete or retry at once.
- Likes and comments sync separately and dont block photo uploads.
### Need more help?
Read `offline-sync` for long offline stretches or contact support from Settings → Help.

View File

@@ -0,0 +1,30 @@
---
title: "<Titel>"
locale: de
slug: <slug>
audience: guest
summary: "Kurzer Teaser für Listenansichten."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: draft
last_reviewed_at: 2025-02-22
owner: <Team oder Person>
related:
- slug: <anderer-slug>
---
> Halte Absätze kurz (max. 3 Sätze) und nutze nummerierte Listen für Abläufe.
## Wann ist dieser Artikel relevant?
Szenario, Voraussetzungen und erwartetes Ergebnis beschreiben.
## Schritte
1. Schrittbeschreibung
2. …
### Tipps
- Optionale Hinweise, Varianten oder FAQs.
### Weitere Hilfe
Auf Support-Optionen oder verknüpfte Artikel verweisen.

View File

@@ -0,0 +1,30 @@
---
title: "<Title>"
locale: en
slug: <slug>
audience: guest
summary: "12 sentence preview for list views."
version_introduced: 2025.4
requires_app_version: "^3.2.0"
status: draft
translation_state: draft
last_reviewed_at: 2025-02-22
owner: <team or person>
related:
- slug: <other-slug>
---
> Keep paragraphs short (max ~3 sentences) and favor ordered lists for procedures.
## When to read this
Explain the scenario, prerequisites, and expected outcome.
## Steps
1. Step explaination
2. …
### Tips
- Optional tips, variations, or FAQs.
### Need more help?
Point to support options or related articles.

View File

@@ -0,0 +1,102 @@
# Photobooth FTP Ingestion
This guide explains how to operate the Photobooth FTP workflow endtoend: provisioning FTP users for tenants, running the ingest pipeline, and exposing photobooth photos inside the Guest PWA.
## Architecture Overview
1. **vsftpd container** (port `2121`) accepts uploads into a shared volume (default `/var/www/storage/app/photobooth`). Each event receives isolated credentials and a dedicated directory.
2. **Control Service** (REST) provisions FTP accounts. Laravel calls it during enable/rotate/disable actions.
3. **Photobooth settings** (Filament SuperAdmin) define global port, rate limit, expiry grace, and Control Service connection.
4. **Ingest command** copies uploaded files into the events storage disk, generates thumbnails, records `photos.ingest_source = photobooth`, and respects package quotas.
5. **Guest PWA filter** consumes `/api/v1/events/{token}/photos?filter=photobooth` to render the “Fotobox” tab.
```
Photobooth -> FTP (vsftpd) -> photobooth disk
photobooth:ingest (queue/scheduler)
-> Event media storage (public disk/S3)
-> packages_usage, thumbnails, security scan
```
## Environment Variables
Add the following to `.env` (already scaffolded in `.env.example`):
```env
PHOTOBOOTH_CONTROL_BASE_URL=https://control.internal/api
PHOTOBOOTH_CONTROL_TOKEN=your-control-token
PHOTOBOOTH_CONTROL_TIMEOUT=5
PHOTOBOOTH_FTP_HOST=ftp.internal
PHOTOBOOTH_FTP_PORT=2121
PHOTOBOOTH_USERNAME_PREFIX=pb
PHOTOBOOTH_USERNAME_LENGTH=8
PHOTOBOOTH_PASSWORD_LENGTH=8
PHOTOBOOTH_RATE_LIMIT_PER_MINUTE=20
PHOTOBOOTH_EXPIRY_GRACE_DAYS=1
PHOTOBOOTH_IMPORT_DISK=photobooth
PHOTOBOOTH_IMPORT_ROOT=/var/www/storage/app/photobooth
PHOTOBOOTH_IMPORT_MAX_FILES=50
PHOTOBOOTH_ALLOWED_EXTENSIONS=jpg,jpeg,png,webp
```
### Filesystem Disk
`config/filesystems.php` registers a `photobooth` disk that must point to the shared volume where vsftpd writes files. Mount the same directory inside both the FTP container and the Laravel app container.
## Control Service Contract
Laravel expects the Control Service to expose:
```
POST /users { username, password, path, rate_limit_per_minute, expires_at, ftp_port }
POST /users/{username}/rotate { password, rate_limit_per_minute, expires_at }
DELETE /users/{username}
POST /config { ftp_port, rate_limit_per_minute, expiry_grace_days }
```
Authentication is provided via `PHOTOBOOTH_CONTROL_TOKEN` (Bearer token).
## Scheduler & Commands
| Command | Purpose | Default schedule |
|---------|---------|------------------|
| `photobooth:ingest [--event=ID] [--max-files=N]` | Pulls files from the Photobooth disk and imports them into the event storage. | every 5 minutes |
| `photobooth:cleanup-expired` | De-provisions FTP accounts after their expiry. | hourly |
You can run the ingest job manually for a specific event:
```bash
php artisan photobooth:ingest --event=123 --max-files=20
```
## Tenant Admin UX
Inside the Event Admin PWA, go to **Event → Fotobox-Uploads** to:
1. Enable/disable the Photobooth link.
2. Rotate credentials (max 10-char usernames, 8-char passwords).
3. View rate limit + expiry info and copy the ftp:// link.
## Guest PWA Filter
The Guest gallery now exposes a “Fotobox” tab (both preview card and full gallery). API usage:
```
GET /api/v1/events/{token}/photos?filter=photobooth
Headers: X-Device-Id (optional)
```
Response items contain `ingest_source`, allowing the frontend to toggle photobooth-only views.
## Operational Checklist
1. **Set env vars** from above and restart the app.
2. **Ensure vsftpd + Control Service** are deployed; verify port 2121 and REST endpoint connectivity.
3. **Mount shared volume** to `/var/www/storage/app/photobooth` (or update `PHOTOBOOTH_IMPORT_ROOT` + `filesystems.disks.photobooth.root`).
4. **Run migrations** (`php artisan migrate`) to create settings/event columns.
5. **Seed default storage target** (e.g., `MediaStorageTarget::create([... 'key' => 'public', ...])`) in non-test environments if not present.
6. **Verify scheduler** (Horizon or cron) is running commands `photobooth:ingest` and `photobooth:cleanup-expired`.
7. **Test end-to-end**: enable Photobooth on a staging event, upload a file via FTP, wait for ingest, and confirm it appears under the Fotobox filter in the PWA.

View File

@@ -0,0 +1,97 @@
# Photobooth Control Service API
The control service is a lightweight sidecar responsible for provisioning vsftpd accounts. Laravel talks to it via REST whenever an Event Admin enables, rotates, or disables the Photobooth feature.
## Authentication
- **Scheme:** Bearer token.
- **Header:** `Authorization: Bearer ${PHOTOBOOTH_CONTROL_TOKEN}`.
- **Timeout:** Configurable via `PHOTOBOOTH_CONTROL_TIMEOUT` (default 5s).
## Endpoints
| Method & Path | Description |
|---------------|-------------|
| `POST /users` | Create a new FTP account for an event. |
| `POST /users/{username}/rotate` | Rotate credentials / extend expiry for an existing user. |
| `DELETE /users/{username}` | Remove an FTP account (called when an event disables Photobooth or expires). |
| `POST /config` | Optionally push global config changes (port, rate-limit, expiry grace) to the control service. |
### `POST /users`
```json
{
"username": "pbA12345",
"password": "F4P9K2QX",
"path": "tenant-slug/123",
"rate_limit_per_minute": 20,
"expires_at": "2025-06-15T22:59:59Z",
"ftp_port": 2121,
"allowed_ip_ranges": ["1.2.3.4/32"],
"metadata": {
"event_id": 123,
"tenant_id": 5
}
}
```
**Response:** `201 Created` with `{ "ok": true }`. On failure return 4xx/5xx JSON with `error.code` + `message`.
Implementation tips:
- Ensure the system user or virtual users home directory is set to the provided `path` (prefixed with the shared Photobooth root).
- Apply the rate limit token-bucket before writing to disk (or integrate with HAProxy).
- Store `expires_at` and automatically disable the account when reached (in addition to Laravels scheduled cleanup).
### `POST /users/{username}/rotate`
```json
{
"password": "K9M4T6QZ",
"rate_limit_per_minute": 20,
"expires_at": "2025-06-16T22:59:59Z"
}
```
- Rotate the password atomically and respond with `{ "ok": true }`.
- If username does not exist return `404` with a descriptive message so Laravel can re-provision.
### `DELETE /users/{username}`
No request body. Delete or disable the FTP account, removing access to the assigned directory.
### `POST /config`
Optional hook used when SuperAdmins change defaults:
```json
{
"ftp_port": 2121,
"rate_limit_per_minute": 20,
"expiry_grace_days": 1
}
```
Use this to reload vsftpd or adjust proxy rules without redeploying the control service.
## Error Contract
Return JSON structured as:
```json
{
"error": {
"code": "user_exists",
"message": "Username already provisioned",
"context": { "username": "pbA12345" }
}
}
```
Laravel treats any non-2xx as fatal and logs the payload (sans password). Prefer descriptive `code` values: `user_exists`, `user_not_found`, `rate_limit_violation`, `invalid_payload`, etc.
## Observability
- Emit structured logs for every create/rotate/delete with event + tenant IDs.
- Expose `/health` so Laravel (or uptime monitors) can verify connectivity.
- Consider metrics (e.g., Prometheus) for active accounts, rotations, and failures.

View File

@@ -0,0 +1,53 @@
# Photobooth Operations Playbook
Use this checklist when bringing Photobooth FTP online for a tenant or debugging ingest issues.
## 1. Provisioning Flow
1. **SuperAdmin config** set defaults in Filament → Platform Management → Photobooth Settings.
2. **Tenant enablement** Event Admin opens the event → Fotobox-Uploads → “Photobooth aktivieren”.
3. Laravel generates credentials and calls the control service (`POST /users`).
4. vsftpd accepts uploads at `ftp://username:password@HOST:PORT/`.
5. `photobooth:ingest` copies files into the hot storage disk and applies moderation/security pipelines.
## 2. Troubleshooting
| Symptom | Action |
|---------|--------|
| Tenants Photobooth page shows “Deaktiviert” immediately | Check `storage/logs/laravel.log` for control-service errors; re-run `photobooth:ingest --event=ID -vv`. |
| Files remain under `/storage/app/photobooth/<tenant>/<event>` | Ensure scheduler (Horizon/cron) runs `photobooth:ingest`; run manual command to force ingestion. |
| Photos missing from guest “Fotobox” tab | Confirm `photos.ingest_source = photobooth` and that `/api/v1/events/{token}/photos?filter=photobooth` returns data. |
| Rate-limit complaints | Inspect control service logs; adjust `PHOTOBOOTH_RATE_LIMIT_PER_MINUTE` and re-save settings (fires `/config`). |
| Credentials leaked/compromised | Click “Zugang neu generieren” in Event Admin; optional `php artisan photobooth:cleanup-expired --event=ID` to force deletion before expiry. |
## 3. Command Reference
```bash
# Manually ingest pending files for a single event
php artisan photobooth:ingest --event=123 --max-files=100
# Check ingest for all active events (dry run)
php artisan photobooth:ingest --max-files=10
# Remove expired accounts (safe to run ad hoc)
php artisan photobooth:cleanup-expired
```
## 4. Pre-flight Checklist for New Deployments
1. `php artisan migrate`
2. Configure `.env` Photobooth variables.
3. Mount shared Photobooth volume in all containers (FTP + Laravel).
4. Verify `MediaStorageTarget` records exist (hot target pointing at the hot disk).
5. Seed baseline emotions (Photobooth ingest assigns `emotion_id` from existing rows).
6. Confirm scheduler runs (Horizon supervisor or system cron).
## 5. Incident Response
1. **Identify scope** which events/tenants are affected? Check ingestion logs for specific usernames/path.
2. **Quarantine** disable the Photobooth toggle for impacted events via Admin UI.
3. **Remediate** fix FTP/control issues, rotate credentials, run `photobooth:ingest`.
4. **Audit** review `photobooth_metadata` on events and `photos.ingest_source`.
5. **Communicate** notify tenant admins via in-app message or email template referencing incident ID.
Keep this playbook updated whenever infra/process changes. PRs to `/docs/photobooth_ftp` welcome.

View File

@@ -115,3 +115,15 @@ When deploying new code:
2. Run migrations & seeders.
3. Recreate worker/horizon containers: `docker compose up -d --force-recreate queue-worker media-storage-worker horizon`.
4. Tail logs to confirm workers boot cleanly and start consuming jobs.
### 8. Running inside Coolify
If you host Fotospiel on Coolify:
- Create separate Coolify “services” for each worker type using the same image and command snippets above (`queue-worker.sh default`, `media-storage`, etc.).
- Attach the same environment variables and storage volumes defined for the main app.
- Use Coolifys “One-off command” feature to run migrations or `queue:retry`.
- Expose the Horizon service through Coolifys HTTP proxy (or keep it internal and access via SSH tunnel).
- Enable health checks so Coolify restarts workers automatically if they exit unexpectedly.
These services can be observed and restarted from Coolifys dashboard; the upcoming SuperAdmin integration will surface the same metrics/actions through a dedicated Filament widget.