Zum Hauptinhalt
Zurück zu Projekten
Görev Kahramanı logo

Görev Kahramanı

Webanwendung

Kurz gesagt

Vorher
Eltern verfolgten Gewohnheiten mit Papierplänen oder mit Apps für Erwachsene; weil ein Kind seine eigene Belohnung selbst freigeben konnte, verlor das System seine Glaubwürdigkeit.
Nachher
Das Kind erledigt Aufgaben auf seinem eigenen Bildschirm, Freigabe und Belohnung liegen allein bei den Eltern; die App lässt sich auf dem Telefon installieren und öffnet sich auch offline.
Was sich geändert hat
Selbst wenn dieselbe Aufgabe zweimal freigegeben wird, gibt es die Belohnung nur einmal; der Wechsel in ein Kinderprofil wird auf dem Server geprüft, und das Verstellen der Geräteuhr bringt keine Serie.
Görev Kahramanı

Eine elterngesteuerte Webanwendung, die tägliche Gewohnheiten von Kindern im Alter von 4–12 Jahren durch Gamification unterstützt. Kinder erledigen Aufgaben, sammeln Sterne und XP, entwickeln ihren Charakter weiter und sammeln Abzeichen. Eltern verwalten Aufgaben, führen Genehmigungsprozesse durch und verfolgen den Fortschritt.

Verwendete Technologien

  • Next.js 16
  • TypeScript
  • Supabase
  • Zustand
  • Zod
  • Vitest
  • Framer Motion

Hauptmerkmale

  • Kindermodus: Aufgabenablauf, Sterne/XP, Levelaufstieg und Charakterentwicklung
  • Elternpanel: Aufgabenverwaltung, Genehmigung/Ablehnung mit Coaching-Notizen
  • Belohnungskatalog-Verwaltung und Belohnungsanfrage-System
  • PWA-Unterstützung — Offline-Nutzung und Startbildschirm-Installation
  • Keine verlorenen Punkte bei gleichzeitigen Änderungen und PIN-Schutz

Entwicklungszeit

2 Monate

Problem

Um die täglichen Gewohnheiten ihrer Kinder zu verfolgen, greifen Eltern entweder zur Papierliste oder zu Aufgaben-Apps, die für Erwachsene entworfen wurden. Beide scheitern an derselben Stelle: Das Kind kann seine eigene Belohnung selbst bestätigen, wodurch das System seine Glaubwürdigkeit verliert. Das eigentliche Problem der Anwendung war nicht die Oberfläche, sondern die Trennung der Berechtigungen.

Nutzer

Zwei unterschiedliche Nutzer in einem Produkt. Ein Kind zwischen 4 und 12: eingeschränktes Lesen und Schreiben, große Touch-Ziele, Belohnungs-Feedback muss sofort sichtbar sein. Ein Elternteil: definiert Aufgaben, bestätigt erledigte oder gibt sie mit einer Coaching-Notiz zurück, verfolgt die wöchentliche Entwicklung — und will sicher sein, dass das Kind in diesen Ablauf nicht eingreifen kann.

Meine Rolle

Alleiniger Entwickler. Produktumfang, Datenmodell, Supabase-Schema und RLS-Policies, die Server-Action-Schicht, zwei getrennte Oberflächen (Kind/Eltern), PWA-Einrichtung, der KVKK-Cookie-Ablauf und das Vercel-Deployment.

Architektur

Eine einzige Next.js-16-App-Router-Anwendung. Der Lesepfad läuft über Server Component → lib/dal/*, der Schreibpfad über Server Action → Zod-Validierung → Supabase. Die Autorisierung ist dreischichtig: Session-Prüfung in proxy.ts, Postgres-RLS-Policies und ein zusätzlicher Guard innerhalb der Server Action. Der Kind-Kontext (activeChild) liegt in Zustand; Serverdaten werden nicht in den Store kopiert. Der Streak-Abgleich erfolgt über einen geplanten Job unter /api/cron/reconcile-streaks. Der zweite Client des Systems liegt in einem eigenen Repository: eine mit SwiftUI geschriebene iOS-Anwendung. Dieser Client bringt kein eigenes Backend mit — er greift auf dasselbe Supabase-Schema zu, sodass Berechtigungsregeln und RLS-Policies mit dem Web identisch sind. Sein heutiger Reifegrad ist ein Gerüst: Elternanmeldung, Kindauswahl und der Ablauf der Panel-Bildschirme stehen, und die Supabase-Client-Konfiguration liegt als optionaler Loader vor — ohne Konfiguration stürzt die App nicht ab, sie läuft ohne Verbindung, und die Bildschirme füllen sich mit Beispieldaten. Die Architekturentscheidung ist also getroffen und bestätigt; die Datenanbindung ist noch nicht abgeschlossen.

  1. Web-AnwendungNext.js 16 App Router · PWA
  2. Zustand · activeChildnur Client-State · keine Serverdaten im Store
  3. proxy.tsSession-Prüfung
  4. LesepfadServer Component → lib/dal/*
  5. SchreibpfadServer Action → Zod-Validierung → Guard
  6. Supabase · PostgresRLS-Policies · verify_child_pin RPC · vergleichende Aktualisierung
  7. /api/cron/reconcile-streaksgeplanter Job · Streak-Abgleich
  8. iOS-Client · SwiftUIeigenes Repository · kein eigenes Backend · dasselbe Supabase-Schema · dieselben RLS-Policies
  9. Dreischichtige Autorisierung: proxy.ts · Postgres-RLS · Server-Action-Guard
Eine einzige Next.js-Anwendung trennt Lese- und Schreibpfad, die Autorisierung wird dreischichtig geprüft — proxy.ts, Postgres-RLS und ein Guard in der Server Action —, während der SwiftUI-Client ohne eigenes Backend auf dasselbe Supabase-Schema zugreift und der Streak über einen geplanten Job abgeglichen wird.

Zentrale Entscheidungen

  1. CAS-artiger Nebenläufigkeitsschutz bei Stern- und XP-Updates

    Bestätigte ein Elternteil dieselbe Aufgabe in zwei Tabs oder tippte das Kind zweimal auf die Schaltfläche, konnte die Belohnung doppelt geschrieben werden. Das Update erfolgt nun im Abgleich mit dem erwarteten aktuellen Wert; der zweite Schreibvorgang wird abgewiesen.

    KompromissBei einer Kollision muss dem Nutzer ein "Erneut versuchen" angezeigt werden; ein stilles Zusammenführen gibt es nicht. Gegenüber einem einfachen UPDATE bedeutet das mehr Code und mehr Fehlerpfade.

  2. PIN-Prüfung in einer Datenbankfunktion statt auf dem Client

    Gelangte die PIN des Kinderprofils in den Browser, käme ein Geschwister oder das Kind selbst leicht daran vorbei. Die verify_child_pin-RPC führt den Hash-Vergleich auf dem Server durch und unterbindet Brute-Force, indem sie aufeinanderfolgende Fehlversuche zählt.

    KompromissJeder Profilwechsel kostet einen Netzwerk-Roundtrip, und im Offline-Betrieb lässt sich das Profil nicht wechseln.

  3. Der Client berechnet den Streak nicht, ein Cron gleicht ihn ab

    Gerätezeit und Zeitzone sind nicht vertrauenswürdig; ein Kind könnte sich durch Ändern des Gerätedatums eine Serie erarbeiten. Der Streak wird serverseitig durch einen geplanten Job neu berechnet.

    KompromissDer Streak kann sich verzögert aktualisieren, erst wenn der Cron gelaufen ist; der Nutzer sieht die Änderung nicht unmittelbar.

Technologiewahl

Supabase wurde gewählt, damit sich der kritische Teil der Autorisierung — dass ein Kind ausschließlich seine eigenen Aufgaben sehen kann — nicht im Anwendungscode, sondern als Datenbank-Policy ausdrücken lässt: Selbst bei einem Fehler in der Anwendungsschicht treten keine Daten aus. Zod dient als einziges Schema und wird sowohl bei der Server-Action-Eingabe als auch auf der Formularseite verwendet. Zustand hält nur kurzlebigen Client-Zustand; die Quelle der Serverdaten ist immer der Server.

Sicherheit

Zwei unabhängige Autorisierungsschichten: Postgres-RLS und ein Guard innerhalb der Server Action — wird eine umgangen, stoppt die andere. Die PIN ist gehasht und mit einem Brute-Force-Zähler versehen. Cloudflare Turnstile ist bei Registrierung, Anmeldung und beim Wechsel Kind→Eltern aktiv. Die Eltern-Aktionssperre wird per Passwortprüfung vorübergehend gelöst. Security-Header und eine Report-Only-CSP sind in next.config.ts definiert. Google Analytics lädt erst nach erteilter Cookie-Einwilligung und nur in der Produktionsumgebung (KVKK).

Performance

Als PWA installierbar, mit Service Worker und einer /offline-Fallback-Seite. 26 Testdateien mit Vitest, schwerpunktmäßig zum Nebenläufigkeitsverhalten der Bestätigungs- und Belohnungsabläufe. Lighthouse mobil (eigene Messung): 100/100 — September 2026. In derselben Messung liegt der LCP-Median bei 1666 ms, die Gesamtblockierzeit bei 1 ms und CLS bei 0.

Ergebnisse

Aktive Entwicklung
2026-03 → 2026-07 · 39 Commits
Nebenläufigkeitsgarantie
Eine doppelte Bestätigung erzeugt keine doppelte Belohnung
Testdateien
26
TypeScript-Quelldateien
139
Plattform
Web (PWA) + nativer iOS-Client

Was ich heute anders machen würde

Heute würde ich die Nebenläufigkeitsgarantie nicht mit CAS in der Anwendungsschicht, sondern direkt als Datenbank-Constraint umsetzen. Bei Ustura habe ich Terminüberschneidungen mit einem Postgres Exclusion Constraint gelöst; dieser Ansatz erfordert weniger Code und verlagert die Garantie aus der Anwendung heraus in die Datenbank selbst. Zweitens würde ich die CSP nicht im Report-Only-Modus belassen, sondern sie vor dem Go-live auf Enforce umstellen — Berichte zu sammeln stoppt keinen Verstoß.

Finden wir gemeinsam den richtigen Einstieg

Sagen Sie mir, was Sie bauen möchten; ich sage Ihnen vorab, wie lange es dauert und was der sinnvolle erste Schritt ist.