Read-only PRD for a coding agent
Lernende wollen Karteikarten effizient erstellen, teilen und zum richtigen Zeitpunkt…
What Lea learned
Leider war ich etwas im Kurs eingeschränkt, da ich mit meinem iPad gearbeitet habe. OpenCode und alle Desktop-Versionen der Ki Modelle konnte ich nur als native App benutzen, trotzdem habe ich gelernt wie man strukturiert Arbeitet und seine Ideen in Prompts umsetzt. Wichtig ist auch die Ki mit Bildern oder mit Beispielen zu unterstützen , um seine Vorstellungen klar zu kommunizieren. Auch die Erkenntnis, dass man für jegliche Sachen, die man benötigt, sich selber zur Hand gehen kann, indem man eine passende App aufbaut, fand ich bemerkenswert.
1. Problem, goal & success metric
Problem: Lernende wollen Karteikarten effizient erstellen, teilen und zum richtigen Zeitpunkt wiederholen, ohne sich um den Lernplan zu kümmern.
Ziel: Eine Web-App zum Erstellen, Lernen und Teilen von Karteikartenstapeln mit Abfrage in Intervallen nach dem Vorbild von Anki.
Erfolgsmetrik: Nutzer lernen mindestens 3 Tage pro Woche; Anteil geteilter Stapel, die von Empfängern übernommen werden.
2. Users & roles
Nutzergruppen:
- Lernende (Schüler, Studierende, Sprachlernende): lernen Stapel mit Abfrage in Intervallen.
- Ersteller: erstellen Stapel und Karten und teilen sie per Link.
- Empfänger: lernen geteilte Stapel schreibgeschützt und übernehmen sie in die eigene Bibliothek.
Nutzerzahlen: Start mit wenigen Nutzern (Pilot ca. 100), langfristig mehrere tausend. Die Architektur muss für steigende Nutzerzahlen ausgelegt sein.
3. Core workflows
Übernahme eines geteilten Baums:
- Der Empfänger startet 'Übernehmen' am Wurzelstapel.
- Die Aktion kopiert immer den gesamten Baum mit allen Unterstapeln und Karten.
- Die Kopie erscheint direkt auf oberster Ebene der eigenen Bibliothek; eine Zielordner-Auswahl gibt es nicht.
- Nach der Übernahme kehrt der Empfänger zur Stapelübersicht zurück, wo der übernommene Stapel oben in der eigenen Bibliothek erscheint; es gibt keinen direkten Sprung in die Lernsitzung.
- Nur der Wurzelstapel der Kopie erhält den Zusatz '(Kopie)' hinter dem Namen; bei Namensgleichheit in der Bibliothek wird eine laufende Nummer ergänzt. Unterstapel behalten ihre Namen unverändert.
- Eine Teilauswahl einzelner Unterstapel gibt es in Version 1 nicht.
- Neutrale Lernwerte: alle Karten der Kopie gelten als neu, Intervall und Faktor werden auf den Startwert gesetzt.
- Die Kopie ist eine eigenständige, unabhängige Kopie.
4. Features & requirements
Neue Karten: Alle neuen Karten eines Stapels erscheinen in der Lernsitzung auf einmal, ohne Obergrenze pro Sitzung, in der Reihenfolge, in der sie angelegt wurden.
Teilen: Der Ersteller sieht keine Rückmeldung der Empfänger; es gibt keine Übersicht oder Zähler über Übernahmen.
5. Scope: must / later / never
Must:
- Konto mit Registrierung und Anmeldung per E-Mail und Passwort
- Bestätigung der E-Mail-Adresse per Link (7 Tage gültig), bevor das Konto nutzbar ist
- Verschachtelte Stapel mit Anlegen, Bearbeiten und Löschen
- Karteneditor mit Vorder- und Rückseite, Erstellen, Bearbeiten und Löschen
- Lernsitzung nur mit den Karten des gewählten Stapels selbst
- Bewertung nochmal / schwer / gut / leicht mit Intervallberechnung nach SM-2
- Link-Teilen eines Stapelbaums und Übernahme als vollständige, unabhängige Kopie
Later:
- Karten zwischen Stapeln verschieben
- Abschlussansicht der Lernsitzung mit Zählung und Schaltfläche 'Fertig'
- Offline-Speicherung von Bewertungen mit Synchronisation
- Widerruf von Links
- Import und Export von Karteikartenstapeln
- Passwortregeln: Groß- und Kleinbuchstabe sowie Ziffer
- Karteikarten mit Bildverdeckung
- Load Balancer und mehrere Server
- iOS und Desktop
- Rückgängigmachen der letzten Bewertung
- Option, Unterstapel in die Lernsitzung einzubeziehen
- Teilauswahl von Unterstapeln bei der Übernahme
- Bestätigung per Link: Wenn die Bestätigungsmail nicht ankommt, ist das Konto erst nach Nachfordern nutzbar
Never:
- Rückmeldung von Empfängern an den Ersteller
- Synchronisation von Änderungen zwischen Original und Kopien
- Kollaboratives Bearbeiten in Echtzeit
- Löschen von Karteikarten beim Schließen der App
- Abfrage von Kontodaten über Registrierung und Anmeldung hinaus
6. Screens & UI
Abschlussansicht: Nach der letzten Karte zeigt die Ansicht die Zählung bewertet, neu und übersprungen sowie die Schaltfläche 'Fertig', die zur Stapelübersicht zurückführt. Karten, die in der Sitzung weder bewertet noch gelöscht wurden, zählen als 'neu'.
Nach dem Übernehmen: Der Empfänger landet in der Stapelübersicht; der übernommene Stapel steht oben in der eigenen Bibliothek. Ein kurzer Hinweis 'Übernommen' erscheint für etwa 3 Sekunden und verschwindet danach wieder. Der Hinweis erscheint bei jeder Übernahme, auch bei einer erneuten; jede Übernahme erzeugt eine neue, eigenständige Kopie.
7. Design system & visual style
Farben Hell-Modus: Hintergrund #FFFFFF bzw. sehr helles Grau, Schrift #2B2B2B.
Farben Dunkel-Modus: Hintergrund #1E1E1E, Schrift #F2F2F2. Akzentfarben unverändert.
Modus-Umschaltung: Die App folgt automatisch der Systemeinstellung (hell/dunkel). In den Einstellungen gibt es zusätzlich einen Schalter zum manuellen Umschalten.
Akzentfarben (beide Modi, für Schaltflächen und Auswahl): Pastellblau #AEC6CF, Pastelllila #C3B1E1, Pastellrosa #F4C2C2.
Zählanzeige: fällige Karten Pfirsich #FFDAC1, neue Karten Hellblau #A8D8EA, gelernte Karten Pastellgrün #B5E5CF.
Eckenradius: 8 px für Schaltflächen und Karten.
Abstände: 16 px zwischen Elementen; Listeneinträge 48 px hoch.
Schrift: eine Schriftart (Systemschrift der Plattform), Fließtext 16 px, Überschriften 20 px fett.
Tonfall: ruhig, pastellig, ohne starke Kontraste.
8. Data model
Geräte-ID: Beim ersten Start wird eine zufällige UUID erzeugt, lokal auf dem Gerät gespeichert und nie verändert. Sie dient nur dem Konfliktvergleich bei gleichem Zeitstempel.
Bewertung (Lernereignis, lokal und auf dem Server):
| field | type | required |
|---|---|---|
| id | uuid | ja |
| card_id | uuid (Karte) | ja |
| rating | text (nochmal, schwer, gut, leicht) | ja |
| rated_at | timestamp (Zeitstempel auf dem Gerät) | ja |
| device_id | uuid (Geräte-ID) | ja |
9. APIs & integrations
Externe Integrationen: Keine Drittanbieter-APIs in Version 1.
E-Mail-Versand: Für Registrierung und Passwort-Zurücksetzen wird ein transaktionaler E-Mail-Dienst über eine API angebunden (Default: Standardanbieter, Zugangsdaten über Umgebungsvariablen).
Interne API: Alle Apps sprechen ausschließlich mit der REST-API; keine direkte Datenbankverbindung.
Default: E-Mail-Dienst als Standardanbieter, in open_questions als Annahme vermerkt.
10. Auth, permissions & security
Passwort: Für Version 1 mindestens 8 Zeichen. Die volle Regel (Groß- und Kleinbuchstabe sowie Ziffer) gilt erst nach Version 1.
Anmeldung: E-Mail und Passwort.
Bestätigung der E-Mail-Adresse: Über einen Link, der 7 Tage gültig ist. Eine neue Bestätigungs-E-Mail kann pro Konto maximal 5 Mal am Tag angefordert werden.
Passwort zurücksetzen: Per E-Mail-Link, der 1 Stunde gültig ist und nur einmal verwendet werden kann.
Datenbankzugriff: Die Datenbank ist nur über das private Hetzner-Netzwerk vom Server aus erreichbar, nicht aus dem Internet; nur die REST-API greift darauf zu.
Zugangsdaten: Alle Zugangsdaten (Datenbank, E-Mail-Dienst) liegen nur als Umgebungsvariablen auf dem Server, nie im Code oder Git-Repository.
Sicherheit: Passwörter gehasht gespeichert, Kommunikation nur über HTTPS.
11. Performance, privacy & accessibility
Performance: Start einer Lernsitzung unter 1 Sekunde bei bis zu 500 fälligen Karten. Antwortzeit der API unter 300 ms im Normalbetrieb.
Skalierung: Architektur für mehrere tausend Nutzer ausgelegt; Backend-Instanzen sind zustandslos.
Datenschutz: Passwörter gehasht gespeichert, Kommunikation nur über HTTPS. Für den Pilot ist eine einfache Datenschutzerklärung vor dem ersten Login Pflicht; Rechtsberatung erfolgt vor dem öffentlichen Start.
Barrierefreiheit: Ziel ist die Unterstützung der Systemschriftgröße und Screenreader-Labels auf allen Bildschirmen.
12. Edge cases & errors
- Gelöschte Karte während der Sitzung: Die Karte wird übersprungen und in der Abschlussansicht als übersprungen gezählt; die Sitzung läuft mit den übrigen fälligen Karten weiter.
- Verbindungsabbruch während der Lernsitzung: Die App zeigt 'Keine Verbindung' und merkt sich die zuletzt angezeigte Karte. Eine nicht gesendete Bewertung zählt als bewertet und ist als 'nicht gespeichert' markiert, bis sie erfolgreich übertragen ist. Sobald die Verbindung zurück ist, wird sie automatisch erneut gesendet. Erst danach setzt die Sitzung nach einem Tippen auf 'Weiter' an der gemerkten Karte fort. Nach erfolgreicher Übertragung verschwindet der Hinweis 'nicht gespeichert'.
- Schließen mit offenen Bewertungen: Beim Schließen erscheint eine kurze Warnung, und die Sitzung bleibt geöffnet, bis alle nicht gespeicherten Bewertungen gesendet sind. Wählt der Nutzer 'Trotzdem beenden', werden nur die nicht gesendeten Bewertungen lokal auf dem Gerät gemerkt und beim nächsten Start der Sitzung automatisch gesendet; alle anderen Daten bleiben auf dem Server.
- Neuinstallation: Nicht gesendete Bewertungen gehen verloren, da die lokale Merkliste mit der App gelöscht wird. Bereits gesendete Bewertungen bleiben auf dem Server erhalten. Es gibt keinen Hinweis auf den Verlust; die verlorenen Bewertungen werden nirgends angezeigt.
13. Stack & constraints
Gerätekennung: Zufällige UUID, beim ersten Start einer Installation erzeugt, lokal gespeichert, nie verändert. Eine Neuinstallation erzeugt eine neue Kennung; eine alte wird nie übernommen.
Speicherung der Bewertungen: Bewertungen liegen auf dem Server in der Datenbank, damit die Lernfortschritte auf jedem Gerät mit demselben Konto sichtbar sind. Nur nicht gesendete Bewertungen werden lokal auf dem Gerät gemerkt und beim nächsten Start der Sitzung automatisch gesendet; alle anderen Daten bleiben ausschließlich auf dem Server.
Netzwerk: Die Lernsitzung braucht in Version 1 eine Internetverbindung; jede Bewertung wird sofort an den Server gesendet.
Konfliktregel: Bei widersprüchlichen Bewertungen derselben Karte gewinnt die Bewertung mit dem späteren Zeitstempel. Bei gleichem Zeitstempel gewinnt die Bewertung mit der lexikalisch kleineren Gerätekennung.
14. Existing code & do-not-change
Projektstart: Neues Projekt, kein bestehender Code.
Vorlagen und externe Dienste: keine, die übernommen werden müssen.
Nicht verändern: Nicht zutreffend, da kein bestehender Code vorhanden ist.
15. Build order
- Konto und Stapelübersicht: Registrierung und Anmeldung per E-Mail und Passwort; Konto ist erst nach Bestätigung des Links nutzbar (7 Tage gültig), neue Bestätigungs-E-Mail maximal 5 Mal am Tag pro Konto. Verschachtelte Stapelliste mit Anlegen, Bearbeiten und Löschen; Löschen eines Unterstapels aktualisiert die Zählungen aller übergeordneten Stapel sofort.
- Karten: Karteneditor mit Vorder- und Rückseite, Erstellen, Bearbeiten und Löschen im gewählten Stapel; Zählungen des Stapels und aller übergeordneten Stapel werden nach jeder Änderung sofort neu berechnet.
- Lernsitzung: Abfrage fälliger Karten, Bewertung nochmal, schwer, gut, leicht, Intervallberechnung nach SM-2 mit Startwert 2,5 und Minimum 1,3; Zählung sofort nach jeder Bewertung; eine während der Sitzung gelöschte Karte wird übersprungen, die Sitzung läuft weiter; Abschlussansicht mit Zählung und Schaltfläche 'Fertig' zur Stapelübersicht.
- Teilen und Übernehmen: Ein Link pro Stapelbaum; Empfänger übernimmt den gesamten Baum als unabhängige Kopie; nur der Wurzelstapel erhält '(Kopie)', alle Karten gelten als neu.
16. Acceptance criteria & tests
- Eine mit 'nochmal' oder 'schwer' bewertete Karte erscheint in derselben Sitzung wieder, bis sie mit 'gut' oder 'leicht' abgeschlossen ist.
- Eine mit 'gut' bewertete Karte erscheint in derselben Sitzung nicht wieder und erst in der nächsten Sitzung.
- Eine mit 'leicht' bewertete Karte erscheint in derselben Sitzung nicht wieder und erst in der nächsten Sitzung mit einem größeren Abstand als bei 'gut'.
- Die Zählung 'fällig' eines Stapels umfasst nur die Karten, die direkt in ihm liegen; Unterstapel haben eine eigene Zählung.
- Nach dem Löschen einer Karte werden die Zählungen des Stapels und aller übergeordneten Stapel sofort neu berechnet, auch in einer laufenden Lernsitzung.
- Eine während der Lernsitzung gelöschte Karte wird in der Abschlussansicht als übersprungen gezählt und die Sitzung läuft mit den übrigen fälligen Karten weiter.
- Nach der letzten Karte zeigt die Abschlussansicht die Zählung (bewertet, neu, übersprungen) und die Schaltfläche 'Fertig', die zur Stapelübersicht führt.
- Karten, die in der Sitzung weder bewertet noch gelöscht wurden, zählen als 'neu'.
- Nach der Übernahme gelten alle Karten der Kopie als neu, Intervall und Faktor stehen auf dem Startwert.
- Beim Übernehmen erhält nur der Wurzelstapel den Zusatz '(Kopie)', Unterstapel behalten ihre Namen.
- Der Hinweis 'Übernommen' erscheint nach jeder Übernahme für etwa 3 Sekunden, auch bei einer erneuten Übernahme desselben Stapels, und jede Übernahme erzeugt eine neue, unabhängige Kopie.
17. Deployment, environments & secrets
Hosting: Ein Hetzner-Cloud-Server mit Docker für Backend-API und Flutter-Web-Dateien.
Datenbank: PostgreSQL als verwalteter Hetzner-Dienst, nur über das private Netzwerk vom Server erreichbar; Backups und Updates durch den Anbieter.
Android: Build der Flutter-App für Android.
Geheimnisse: Alle Zugangsdaten für Datenbank und E-Mail-Dienst liegen ausschließlich als Umgebungsvariablen auf dem Server, nie im Code oder Git-Repository.
18. Open questions & assumptions
Bestätigt: Die Lernsitzung braucht in Version 1 eine Internetverbindung; Bewertungen werden sofort auf dem Server gespeichert.
Später: Offline-Speicherung von Bewertungen mit Synchronisation.
Default: Bestätigungs-E-Mail ist Pflicht; ungültig gewordene Links werden durch eine neue Bestätigungs-E-Mail ersetzt.
Default: E-Mail-Dienst als Standardanbieter, Zugangsdaten über Umgebungsvariablen.
Offen: Rechtsberatung und endgültige Datenschutzerklärung vor dem öffentlichen Start.