PhotoUpload component (camera and file picker, preview, replace/remove), photo next to task and model solution in AttemptReview, parent-triggered AI grading button visible only when the status offers photo grading, retention setting in the admin settings editor, bUnit coverage. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Familienplaner
Digitaler Familienplaner als Progressive Web App: Einkaufsliste, Essenplan, Aufgaben & Ämtchen, Familienkalender (inkl. Abo für iPhone/Outlook) und Chat – für Smartphone, Tablet und Desktop.
Status: Phasen 1–6 sind umgesetzt: Login, Rollenmatrix, Benutzerverwaltung, Familieneinstellungen, Audit-Log, Einkaufslisten (Echtzeit, offline nutzbar), Essenplan (Wochenraster, Wünsche der Kinder, Zutaten auf die Einkaufsliste), Aufgaben & Ämtchen (Wiederholungen, Eltern-Bestätigung, Punkte, Kinderansicht, offline erfassbar, Push-Erinnerungen vorbereitet), Familienkalender (mehrere Kalender mit Rechten, Serien mit Ausnahmen, Agenda/Tag/Woche/Monat, Abo für iPhone/Outlook, ICS-Import), PWA-Grundgerüst, Aspire- und Docker-Betrieb. Die Fachfunktionen folgen phasenweise, siehe
docs/ROADMAP.md.
- Architektur:
docs/ARCHITECTURE.md - Entscheidungen:
docs/adr/
Voraussetzungen (Entwicklung)
- .NET SDK 10 (getestet mit 10.0.300)
- Docker Desktop bzw. Docker Engine (für SQL Server)
- optional: Aspire CLI (
aspire run)
Entwicklung
dotnet tool restore
aspire run # oder: dotnet run --project src/FamilyPlanner.AppHost
Das Aspire-Dashboard öffnet sich automatisch (Login-Link steht in der Konsole). Die App läuft unter https://localhost:7264. Beim ersten Start wird der SQL-Server-Container mit persistentem Volume angelegt, der MigrationService migriert die Datenbank und legt den Initial-Admin an:
| Benutzer | Passwort | Hinweis |
|---|---|---|
admin |
Admin123!ChangeMe |
nur lokal (src/FamilyPlanner.AppHost/appsettings.Development.json), muss beim ersten Login geändert werden |
Das Passwort lässt sich per User Secrets überschreiben:
dotnet user-secrets set "Parameters:seed-admin-password" "..." --project src/FamilyPlanner.AppHost.
Push-Erinnerungen (optional)
Erinnerungen an Aufgaben kommen per Web Push (ADR-0014). Dafür braucht der Server ein VAPID-Schlüsselpaar – ohne Schlüssel ist die Funktion ausgeschaltet. Schlüssel erzeugen und lokal als Aspire-Parameter hinterlegen:
dotnet run tools/generate-vapid-keys.cs # gibt Schlüssel + passende user-secrets-Befehle aus (nicht einchecken!)
cd src/FamilyPlanner.AppHost
dotnet user-secrets set "Parameters:vapid-public-key" "<öffentlicher Schlüssel>"
dotnet user-secrets set "Parameters:vapid-private-key" "<privater Schlüssel>"
Danach kann jedes Familienmitglied im Benutzermenü unter Benachrichtigungen Erinnerungen für sein Gerät aktivieren (iPhone/iPad: erst „Zum Home-Bildschirm“ hinzufügen, dann in der installierten App aktivieren).
Tests
dotnet build FamilyPlanner.slnx
dotnet test --solution FamilyPlanner.slnx # Integrationstests benötigen Docker
Produktivbetrieb (Docker Compose)
cd deploy
cp .env.example .env # Passwörter und Domain anpassen
docker compose up -d --build # ohne Reverse Proxy, Web auf 127.0.0.1:8080
# oder mit automatischem HTTPS (Caddy + Let's Encrypt, Ports 80/443):
docker compose --profile proxy up -d --build
Die App benötigt HTTPS (sichere Cookies). Ohne Caddy funktioniert der Login nur über http://localhost oder hinter
einem eigenen Reverse Proxy mit TLS.
Konfiguration (deploy/.env)
| Variable | Bedeutung |
|---|---|
SQL_SA_PASSWORD |
Passwort des SQL-Server-Administrators (komplex, min. 8 Zeichen) |
MSSQL_PID |
SQL-Server-Edition (Express = kostenlos) |
ADMIN_USERNAME, ADMIN_PASSWORD, ADMIN_EMAIL |
Initial-Admin, nur beim allerersten Start; Passwortwechsel wird erzwungen |
FAMILY_NAME |
Familienname (Vorbelegung der Familieneinstellungen beim ersten Start) |
WEB_BIND, WEB_PORT |
Host-Bindung des Web-Containers ohne Caddy |
DOMAIN |
Domain für Caddy/Let's Encrypt (Profil proxy) |
REGISTRY, TAG |
optionales Image-Präfix und Tag |
VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, VAPID_SUBJECT |
optional: Web-Push-Erinnerungen (Schlüssel mit dotnet run tools/generate-vapid-keys.cs); leer = aus |
Weitere Einstellungen (alle Dienste) folgen der ASP.NET-Core-Konvention Abschnitt__Schlüssel, z. B.
RateLimiting__LoginPermitLimit=10 (Api) oder Features__PinLogin=true (Api, schaltet den vorbereiteten PIN-Login für Kinder frei).
Benutzer, Familieneinstellungen (Familienname, Zeitzone, Essenplan, Mahlzeiten, Aufgaben-Kategorien, Punktesystem, Gast-Rechte) und das Protokoll administrativer Aktionen verwaltet der Administrator in der App unter Verwaltung.
Update
cd deploy
git pull
docker compose up -d --build # Migrationen laufen automatisch über den migrations-Container
Backup & Restore
cd deploy
./scripts/backup.sh # schreibt backups/familyplanner-<datum>.bak
./scripts/restore.sh backups/familyplanner-20261009-120000.bak
Backups liegen zusätzlich im Docker-Volume sql-backup (14 Tage). Für eine regelmäßige Sicherung z. B. per Cron:
0 3 * * * cd /opt/familyplanner/deploy && ./scripts/backup.sh.
Kalender-Abos (iPhone/Outlook)
In der App unter Kalender › Filter-Menü › Kalender abonnieren einen Abo-Link erstellen: alle Termine, nur die eigenen (Personen-Tag) oder ein einzelner Kalender, optional mit Aufgaben. Der Link wird nur einmal angezeigt (mit QR-Code) und funktioniert wie ein Passwort; er lässt sich jederzeit neu erzeugen oder widerrufen. Administratoren sehen und widerrufen alle Abos unter Verwaltung › Kalender.
- iPhone/iPad: „In Kalender-App öffnen“ antippen oder den QR-Code scannen. Alternativ Einstellungen › Apps › Kalender › Kalender-Accounts › Account hinzufügen › Andere › Kalenderabo hinzufügen und den https-Link einfügen.
- Outlook (Web/neues Outlook): Kalender › Kalender hinzufügen › Aus dem Internet abonnieren und den https-Link einfügen. Outlook aktualisiert Abos nur alle paar Stunden.
- Google Kalender: Weitere Kalender „+“ › Per URL.
Voraussetzungen: Die App muss für die Geräte per HTTPS mit gültigem Zertifikat erreichbar sein (z. B. Caddy-Profil proxy).
Abos sind nur lesend; Änderungen erfolgen in der App (bidirektionale Synchronisation: ADR-0017).
Der Feed-Endpunkt ist auf 60 Abrufe pro Minute und IP begrenzt (RateLimiting__FeedPermitLimit).
ICS-Import (Schulferien, Müllabfuhr …): Kalender › Filter-Menü › .ics importieren bzw. Verwaltung › Kalender. Bereits importierte Termine (gleiche UID) werden übersprungen; nicht unterstützte Wiederholungsregeln werden im Ergebnis genannt.