Putzliga
Putzliga ist eine moderne, leichte Haushaltsaufgaben-Web-App mit spielerischem Charakter. Version 1 setzt auf Flask, SQLite, Jinja-Templates, responsives CSS, minimales JavaScript und eine saubere PWA-/Web-Push-Basis. Die App ist für mehrere Nutzer ausgelegt, läuft lokal sehr unkompliziert und ist so vorbereitet, dass sie auf Cloudron direkt als Container-App betrieben werden kann.
Features
- Mehrere Nutzer mit Login, Admin-Nutzermanagement und Profil-/Avatar-Einstellungen
- Trennung zwischen
TaskTemplateundTaskInstance - Aufgaben anlegen, bearbeiten, zuweisen und erledigen
- Wiederholungen für einmalig, alle X Tage, alle X Wochen und alle X Monate
- Saubere Erledigungslogik für fremd zugewiesene Aufgaben mit Auswahl, wer wirklich erledigt hat
- Statuslogik für offen, bald fällig, überfällig und erledigt
Meine Aufgaben,Alle Aufgaben,Aufgabe erstellen,Kalender/Liste,Highscoreboard,Optionen- Monats-Highscore mit Badge-Boni und Balkendarstellung
- Monatsarchiv über
MonthlyScoreSnapshot - PWA mit
manifest.json, Service Worker, App-Icons und iOS-freundlicher Installationsbasis - Echte Web-Push-Architektur mit gespeicherten
PushSubscriptions - CLI-Kommandos für Archivierung und serverseitig triggerbare Benachrichtigungen
- Cloudron-/Container-tauglicher Start mit
start.sh,DockerfileundCloudronManifest.json - Keine freie Registrierung nach dem ersten Nutzer; weitere Nutzer lassen sich kontrolliert per CLI anlegen
- Dauerhaft gespeicherte Badges pro Nutzer mit eigener Admin-Badge-Seite
Projektstruktur
app/
routes/
services/
static/
css/
fonts/
icons/
images/
js/
manifest.json
service-worker.js
templates/
auth/
partials/
scoreboard/
settings/
tasks/
app.py
config.py
seed.py
start.sh
Dockerfile
CloudronManifest.json
requirements.txt
.env.example
scripts/
data/
Lokale Daten vs. Cloudron-Inhalte
Die App ist jetzt so vorbereitet, dass lokale Entwicklungsdaten nicht versehentlich mit nach Cloudron wandern:
data/ist in.gitignoreausgeschlossen und wird nicht committeddata/ist zusätzlich in.dockerignoreausgeschlossen und landet nicht im Docker-Build-Kontext- Uploads liegen standardmäßig ebenfalls unter
data/uploadsund bleiben damit lokal bzw. im persistenten Cloudron-Storage - Beim ersten Cloudron-Start wird keine lokale Entwicklungsdatenbank ins Image kopiert
Damit kannst du lokal mit Seed-Daten entwickeln und online unabhängig davon echte Inhalte pflegen.
Lokales Setup
1. Abhängigkeiten installieren
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
2. Umgebungsvariablen setzen
cp .env.example .env
Wichtige Variablen:
SECRET_KEY: Flask Secret KeyDATA_DIR: Persistentes DatenverzeichnisDATABASE_PATH: SQLite-DateiUPLOAD_FOLDER: Upload-Verzeichnis für AvatareAPP_BASE_URL: Vollständige Basis-URL der App, wichtig für Push-LinksAPP_TIMEZONE: StandardmäßigEurope/BerlinVAPID_PUBLIC_KEY/VAPID_PRIVATE_KEY: Web-Push-SchlüsselVAPID_CLAIMS_SUBJECT: Kontaktadresse für VAPID
3. App-Icons erzeugen
Die Raster-Icons liegen als generierte Dateien im Projekt. Falls du sie neu erzeugen willst:
python scripts/generate_assets.py
4. Datenbank und Seed-Daten anlegen
flask --app app.py init-db
python seed.py
Demo-Logins:
mail@hnz.io/putzliga123(Admin)anna@putzliga.local/putzliga123ben@putzliga.local/putzliga123
Nutzer anlegen
Freie Registrierung ist deaktiviert, sobald mindestens ein Nutzer existiert.
- Wenn die Datenbank noch leer ist, darf genau der erste Nutzer über
/registerangelegt werden. - Weitere Nutzer legst du kontrolliert per CLI an:
flask --app app.py create-user
Admins können Nutzer zusätzlich direkt in der App unter Optionen -> Profil & Team verwalten.
Badges
Badges werden dauerhaft pro Nutzer gespeichert und automatisch freigeschaltet. Die Badge-Regeln werden für Admins auf einer eigenen Seite unter Optionen -> Badges gepflegt.
5. Entwicklungsserver starten
flask --app app.py run --debug
oder produktionsnah:
./start.sh
Seed-Daten
Die Seed-Datei erzeugt:
- 2 Beispielnutzer
- wiederkehrende und einmalige Vorlagen
- offene, bald fällige, überfällige und erledigte Aufgaben
- Punkte im aktuellen Monat
- erledigte Aufgaben aus dem Vormonat, damit das Archiv direkt sichtbar ist
- Standard-Badges für Frühstarter, Serien und Monatsmenge
Datenmodell
Umgesetzt sind die Kernmodelle:
UserTaskTemplateTaskInstanceMonthlyScoreSnapshotPushSubscriptionNotificationLog
Zusätzlich für Version 1:
BadgeDefinitionfür pflegbare Badge-Regeln in den Optionen
Wichtig: TaskTemplate beschreibt die wiederverwendbare Vorlage, TaskInstance die konkrete Aufgabe mit Fälligkeit, Status und tatsächlicher Erledigung.
Monatsarchivierung
Putzliga speichert keine monatlichen Punktetotale als Live-Zähler. Stattdessen wird der Monatsstand aus erledigten TaskInstances berechnet. Dadurch startet jeder neue Monat automatisch bei 0, weil nur Aufgaben des aktuellen Monats zählen.
Die Archivierung funktioniert so:
- Vor Requests wird geprüft, ob bis zum Vormonat Archive fehlen
- Fehlende Monate werden als
MonthlyScoreSnapshoterzeugt - Archivwerte enthalten erledigte Aufgaben und Badge-Boni des jeweiligen Monats
- Frühere Monate bleiben dauerhaft sichtbar
Zusätzlicher CLI-Trigger:
flask --app app.py archive-months
Push-Benachrichtigungen
Putzliga nutzt echte Web-Push-Benachrichtigungen mit Service Worker und VAPID.
Architektur
- Browser registriert Service Worker
- Subscription wird pro Nutzer in
PushSubscriptiongespeichert - Server versendet über
pywebpush - Versand ist getrennt in Prüf- und Ausführungslogik
- Logs werden in
NotificationLogdedupliziert
Verfügbare Trigger
flask --app app.py notify-due
flask --app app.py notify-monthly-winner
notify-due:
- prüft offene Aufgaben, die heute oder morgen fällig sind
- berücksichtigt die Nutzeroption
notification_task_due_enabled
notify-monthly-winner:
- sendet am 1. des Monats ab 09:00 Uhr
- verweist auf das Scoreboard/Archiv des letzten Monats
- berücksichtigt
notification_monthly_winner_enabled
Für iPhone/iPad muss zusätzlich sichergestellt sein, dass der Server ausgehend Apple Web Push erreichen kann. Laut WebKit sollten dafür Verbindungen zu *.push.apple.com möglich sein.
Produktiver Betrieb
Auf Cloudron oder einem anderen Server solltest du diese Kommandos regelmäßig per Cronjob oder Task ausführen, zum Beispiel:
flask --app /app/app.py notify-due
flask --app /app/app.py notify-monthly-winner
iPhone-/iOS-Hinweis
Web-Push auf iPhone/iPad funktioniert nur in neueren iOS-/iPadOS-Versionen, wenn die Web-App über Safari zum Home-Bildschirm hinzugefügt wurde. Innerhalb eines normalen Safari-Tabs stehen Push-Berechtigungen nicht zuverlässig zur Verfügung.
PWA
Enthalten sind:
app/static/manifest.jsonapp/static/service-worker.jsapp/static/images/pwa-icon-192.pngapp/static/images/pwa-icon-512.pngapp/static/images/apple-touch-icon.pngapp/static/images/pwa-badge.png
Der Service Worker cached die App-Shell und Assets pragmatisch für eine stabile Basis. Für Version 1 ist das bewusst schlank gehalten.
Branding und Assets aus heinz.marketing
Aus ../heinz.marketing wurden bewusst nur verwertbare Grundlagen übernommen:
InterundSpace Groteskauscss/fonts/- ausgewählte lokale SVG-Icons aus
css/fontawesome-pro-plus-7.0.0-web/svgs-full/chisel-regular/
Diese Assets wurden nicht unverändert als fertiges Branding übernommen. Putzliga nutzt darauf aufbauend:
- eine eigene helle, iOS-nahe Farbwelt
- ein neues App-Logo (
app/static/images/logo.svg) - ein eigenes Favicon (
app/static/images/favicon.svg) - eigene generierte PWA-Raster-Icons (
scripts/generate_assets.py)
Cloudron
Cloudron-Dateien im Projekt:
Dockerfilestart.shCloudronManifest.json
Die Manifest- und Docker-Struktur orientiert sich an der aktuellen Cloudron-Dokumentation für Docker-/Container-Apps:
https://docs.cloudron.io/docker/
Wichtige Punkte für Cloudron
- App hört auf
PORTund standardmäßig auf8000 DATA_DIRundUPLOAD_FOLDERsollten im persistenten Storage liegen- SQLite-Datei liegt standardmäßig unter
/app/data/putzliga.db start.shinitialisiert die DB und startet GunicornAPP_BASE_URLkann auf Cloudron überCLOUDRON_APP_ORIGINgesetzt oder daraus abgeleitet werden- Lokale Testdaten aus
data/werden weder committed noch in das Docker-Image gepackt
Beispielstart in Cloudron-/Container-Umgebungen
./start.sh
Hilfsskripte
VAPID-Schlüssel generieren:
python scripts/generate_vapid_keys.py
Der ausgegebene VAPID_PRIVATE_KEY ist bereits .env-freundlich mit escaped Newlines formatiert. config.py wandelt \\n beim Start automatisch in echte Zeilenumbrüche zurück.
Icons neu generieren:
python scripts/generate_assets.py
Hinweise für spätere Erweiterungen
- Maluslogik für verspätete Erledigungen kann an
compute_monthly_scores()undTaskInstanceergänzt werden - echte Admin-/Rollenrechte können ergänzt werden, aktuell dürfen bewusst alle Nutzer Aufgaben pflegen
- Scheduler kann auf Cloudron später als separater Task sauber ausgelagert werden
- Badge-Awards könnten in einer eigenen Tabelle historisiert werden, falls spätere Regeln rückwirkungsfrei versioniert werden sollen