Read-only PRD for a coding agent
Rezepte und Nährwerte sind verstreut und nicht verlässlich.
1. Problem, goal & success metric
Problem: Rezepte und Nährwerte sind verstreut und nicht verlässlich.
Ziel: Ein gemeinsames Rezeptebuch für mich und meine Freunde, mit Rezepten erstellen, speichern, sortieren und durchsuchen.
Erfolgskriterium: Jedes Rezept zeigt Nährwerte pro Portion aus verifizierten Quellen, inklusive Makro-, Mikronährstoffen und Aminosäurenprofil.
2. Users & roles
- Admin: du; verwaltet die Gruppe und lädt Freunde per Link ein.
- Mitglied: eingeladene Freunde; legen Rezepte an, bearbeiten alle Rezepte der Gruppe und stellen gelöschte Rezepte wieder her.
- Nährwert-Einstellung: Nach dem ersten Anmelden wird gefragt, ob Nährwerte angezeigt werden sollen (Ja/Nein). Die Antwort wird pro Person im Profil gespeichert und ist jederzeit änderbar.
- Gruppengröße: unter 10 Personen.
3. Core workflows
- Admin lädt Freunde per Link ein; Freunde melden sich an.
- Mitglied legt Rezept an: Titel, Portionen, Zutaten (Zutat aus BLS/USDA wählen, Menge + Einheit), Schritte.
- Speichern; Nährwerte pro Portion werden automatisch berechnet und angezeigt.
- Rezepte sortieren (Titel, Datum, Kategorie, Tags) und durchsuchen (Titel, Zutaten, Tags).
- Rezept öffnen: Nährwerte pro Portion, Makro-, Mikronährstoffe, Aminosäurenprofil, Quelle je Zutat.
4. Features & requirements
Saison-Vorschläge (später):
- Eigener Tab mit Rezepten aus der eigenen Gruppe, die mindestens eine Saisonzutat im aktuellen Kalendermonat haben. Alle anderen Rezepte sind ausgeblendet.
- Der aktuelle Kalendermonat wird beim Öffnen automatisch verwendet, bestimmt über die Zeitzone des Geräts; eine Monatsauswahl gibt es nicht.
- Die Liste wird beim Öffnen des Tabs berechnet; Änderungen an Zutaten oder Rezepten erscheinen erst beim nächsten Öffnen.
- Jede Zutat kann mehrere Monatsbereiche haben (z. B. Spargel: April bis Juni und September bis Oktober); Bereiche dürfen über den Jahreswechsel gehen (z. B. Oktober bis Februar) und sind inklusive Start- und Endmonat.
- Gruppierung nach Anzahl der Saisonzutaten, absteigend, mit Überschrift je Gruppe nur als Zahl (z. B. „3 Saisonzutaten“); innerhalb einer Gruppe alphabetisch nach Titel.
- Zutaten, die nicht in der Saison-Liste im Code stehen, werden still ignoriert und nicht angezeigt; sie zählen nicht als Saisonzutaten.
- Keine Suche im Saison-Tab.
5. Scope: must / later / never
- Name at least 2 things the agent must not build
Must:
- Rezepte erstellen, speichern, sortieren, suchen
- Nährwerte pro Portion mit Makro-, Mikronährstoffen und Aminosäurenprofil
- Gemeinsame Gruppe mit Einladung
Later:
- Fotos, Import von Rezepten, Wochenplaner
- Tab mit Rezeptvorschlägen aus der eigenen Sammlung, basierend auf saisonalen Zutaten in Deutschland
Never:
- Eigene Lebensmittelquelle ohne Nachweis; Medizinische Ernährungsberatung
6. Screens & UI
Saison-Tab: Eigener Tab neben der allgemeinen Rezeptübersicht, ohne Suche. Oben steht der Hinweis mit dem aktuell verwendeten Monat, z. B. „Saison im Mai“.
Gruppen: Rezepte sind nach Anzahl der Saisonzutaten gruppiert; jede Gruppe hat nur die Überschrift mit der Zahl, z. B. „3 Saisonzutaten“, ohne zusätzliche Zeile. Innerhalb jeder Gruppe alphabetisch nach Titel. Es gibt keine Gesamtzeile.
Leerer Zustand: Ohne Rezept mit einer Saisonzutat im aktuellen Monat erscheint der Hinweis „Gerade keine Vorschläge“.
Sichtbarkeit: Nur Rezepte der eigenen Gruppe mit mindestens einer Saisonzutat im aktuellen Monat.
7. Design system & visual style
Komponenten: Kacheln für Rezepte, Foto-Rahmen (rund), Formularfelder, Buttons, Papierkorb-Liste; Vorlage: Beispielbild mit Kachel-Raster und Detailseite.
Farben: Akzent #2E7D32 (Grün); Hintergrund hell, Text dunkel; dunkler Modus folgt dem Gerät.
Schrift: Überschriften in Raleway (serifenfrei); kleine Texte und Untertitel in einer Serifenschrift; Textblöcke wie die Rezeptanleitung serifenfrei.
Form und Abstand: Ecken 8 px abgerundet; Abstand 16 px; Foto-Rahmen rund.
Fotos: Eigenes Foto wird hochgeladen und rund angezeigt (Übersicht und Detail); ohne eigenes Foto wird ein Webfoto unter dem Rezeptnamen gezeigt; das Farbschema kann aus dem Foto abgeleitet werden.
Ton: ruhig, klar, deutsch.
Vorbild: images/Screenshot-2026-10-22-at-09.31.49.jpg (Kacheln mit runden Fotos, Detailseite mit großem Foto, Zutatenreihe, nummerierte Anleitung).
8. Data model
| Tabelle | Feld | Typ | Pflicht |
|---|---|---|---|
| Group | id | uuid | ja |
| Group | name | text | ja |
| Group | created_at | timestamp | ja |
| Membership | user_id | uuid | ja |
| Membership | group_id | uuid | ja |
| Membership | role | admin / member | ja |
| Profile | user_id | uuid | ja |
| Profile | show_nutrition | boolean | ja |
| Profile | answered_at | timestamp | nein |
| Recipe | id | uuid | ja |
| Recipe | group_id | uuid | ja |
| Recipe | title | text | ja |
| Recipe | servings | integer, > 0 | ja |
| Recipe | category | text | nein |
| Recipe | tags | text[] | nein |
| Recipe | photo_url | text | nein |
| Recipe | created_by | uuid | ja |
| Recipe | created_at / updated_at | timestamp | ja |
| Recipe | deleted_at | timestamp | nein |
| Ingredient | id, recipe_id | uuid | ja |
| Ingredient | food_source | BLS / USDA | ja |
| Ingredient | food_code | text | ja |
| Ingredient | name | text | ja |
| Ingredient | amount, unit | number, text | ja |
| Step | id, recipe_id | uuid | ja |
| Step | position | integer | ja |
| Step | text | text | ja |
| NutrientValue | food_source, food_code, nutrient, value, unit | nur lesend, aus BLS/USDA importiert | ja |
Saison-Liste: liegt im Code (Zutat, ein oder mehrere Monatsbereiche), hat keine Tabelle in der Datenbank.
Zutatensuche: Nur nach Name; standardmäßig nur rohe, unverarbeitete Zutaten.
Papierkorb: Rezepte mit deleted_at gelten als gelöscht und sind 48 Stunden wiederherstellbar; danach entfernt ein geplanter Job sie endgültig.
Nährwerte: werden nur berechnet und angezeigt, wenn Profile.show_nutrition true ist.
9. APIs & integrations
Saison-Abgleich:
- Die feste Saison-Liste im Code wird mit den Zutatennamen aus dem BLS/USDA-Import abgeglichen.
- Vergleich ohne Beachtung von Groß-/Kleinschreibung und Leerzeichen am Rand.
- Bei mehreren Treffern hat der BLS-Eintrag Vorrang, sonst USDA.
- Zutaten ohne Treffer in der Saison-Liste werden ignoriert.
- Keine Live-Abfragen; der Abgleich erfolgt im Code beim Öffnen des Saison-Tabs.
10. Auth, permissions & security
- Anmeldung: E-Mail-Magic-Link über Supabase Auth, kein Passwort.
- Einladung: Admin erzeugt einen Einladungslink für die Gruppe; wer den Link öffnet und sich per E-Mail-Link anmeldet, wird Mitglied.
- Rollen: Admin (verwaltet Gruppe, lädt ein), Mitglied (legt Rezepte an, bearbeitet alle Rezepte der Gruppe, löscht nach Bestätigung, stellt aus dem Papierkorb wieder her).
- Sichtbarkeit: Nur Mitglieder der Gruppe sehen Rezepte; Zugriff über Row-Level-Security in Supabase.
- Nährwert-Einstellung: Pro Person im Profil gespeichert; nach dem ersten Login gefragt; nur der eigene Nutzer kann sie ändern und jederzeit umstellen.
11. Performance, privacy & accessibility
Leistung: Rezeptliste lädt in unter 2 Sekunden bei bis zu 500 Rezepten.
Datenschutz:
- Nur Supabase als Datenspeicher; keine Tracker, keine Werbe-SDKs.
- Rezepte sind nur für Gruppenmitglieder sichtbar.
Barrierefreiheit:
- Textgröße folgt der Geräteschrift (skaliert mit).
- Kontrast mindestens WCAG AA.
- Alternativtext für alle Fotos.
- Bedienung per Tastatur möglich.
12. Edge cases & errors
- Saison-Tab ohne Vorschläge: Hinweis „Gerade keine Vorschläge“ statt leerer Seite.
- Saison-Liste: Zutaten, die nicht in der Saison-Liste im Code stehen, werden ignoriert und zählen nicht als Saisonzutaten.
- Monatsbereich über den Jahreswechsel: z. B. Oktober bis Februar gilt als zusammenhängender Bereich.
- Änderungen an Rezepten: erscheinen im Saison-Tab erst beim nächsten Öffnen.
13. Stack & constraints
- Frontend: Web-App (Next.js), gehostet bei Vercel (kostenloser Tarif).
- Backend/Datenbank: Supabase (PostgreSQL, eingebaute Anmeldung per Magic Link, Row-Level-Security), kostenloser Tarif.
- Speicherung: zentral in Supabase; kein eigener Server, kein eigener API-Server.
- Begründung: eine Datenbank, ein Host, keine zusätzlichen Dienste. Supabase ist die einzige gehostete Datenbank, die Teilen zwischen Geräten ohne eigenen Server ermöglicht.
14. Existing code & do-not-change
Not needed: neues Projekt ohne bestehenden Code.
15. Build order
- Anmeldung und Gruppe: Magic-Link-Anmeldung, Einladungslink erzeugen und einlösen, Admin/Mitglied-Rollen, Zugriff nur für Gruppenmitglieder (Row-Level-Security). Lauffähig: Freund kann per Link beitreten und sich anmelden.
- Rezepte anlegen und anzeigen: Formular mit Titel, Portionen, Zutaten (Menge, Einheit), Schritten und Foto-Feld; Liste und Detailseite mit rundem Foto bzw. Webfoto. Lauffähig: Rezept speichern und in der Liste sehen.
- Sortieren und Suche: nach Titel, Datum, Kategorie, Tags; Suche über Titel, Zutaten, Tags (nicht Nährwerte); Hinweis bei keinen Treffern. Lauffähig: Rezepte finden und sortieren.
- Nährwerte aus BLS/USDA: Zutatenauswahl aus importierten Daten, automatische Berechnung pro Portion (Makro, Mikro, Aminosäuren), Quelle je Zutat, Hinweis „keine Daten“; bei Nährwerte „Nein“ kein Bereich und kein Hinweis. Lauffähig: Nährwerte am Rezept sichtbar.
- Papierkorb: Löschen mit Bestätigung, Papierkorb-Ansicht mit Restzeit, Wiederherstellen durch jedes Gruppenmitglied, geplanter Job löscht nach 48 Stunden endgültig. Lauffähig: Löschen, Wiederherstellen und automatische Entfernung funktionieren.
- Saison-Vorschläge (später): Tab mit Vorschlägen aus der Sammlung, Saisonliste im Code, Regel: mindestens eine Saisonzutat im aktuellen Monat. Lauffähig: Vorschläge erscheinen im Tab.
16. Acceptance criteria & tests
- Anmeldung per E-Mail-Link ohne Passwort funktioniert; abgelaufener oder ungültiger Einladungslink zeigt Hinweis und Möglichkeit, neuen Link anzufordern.
- Rezept mit Portionen 0 wird abgelehnt mit Fehlermeldung am Feld; mit Titel, Portionen > 0 und mindestens einer Zutat wird gespeichert.
- Bei Nährwerte „Ja“ erscheinen Nährwerte pro Portion mit Makro-, Mikronährstoffen und Aminosäurenprofil; Quelle je Zutat ist sichtbar; fehlende Daten werden als „keine Daten“ markiert.
- Bei Nährwerte „Nein“ erscheint in der Detailansicht kein Nährwertbereich und kein Hinweis darauf.
- Gelöschtes Rezept erscheint im Papierkorb mit Restzeit und lässt sich von jedem Gruppenmitglied wiederherstellen.
- Ein Rezept, dessen deleted_at mehr als 48 Stunden zurückliegt, ist nach dem geplanten Job nicht mehr in der Datenbank.
- Suche findet Rezepte über Titel, Zutat und Tag, aber nicht über Nährwerte; ohne Treffer erscheint „Keine Rezepte gefunden“.
- Zutatensuche beim Erfassen sucht nur nach dem Namen und zeigt standardmäßig rohe, unverarbeitete Zutaten.
- Eigenes Foto erscheint rund in Liste und Detail; ohne Foto wird das Webfoto unter dem Namen gezeigt; jedes Foto hat einen Alternativtext.
- Texte skalieren mit der Geräteschrift; Kontrast erfüllt WCAG AA.
- Netzwerkfehler beim Speichern lässt die Eingabe stehen und erlaubt einen erneuten Versuch.
- App ist auf Handy und Desktop nutzbar.
17. Deployment, environments & secrets
- Umgebung: eine einzige Produktionsumgebung: Vercel (Web-App) und Supabase (Datenbank und Anmeldung), beide kostenlos.
- Testen: neue Funktionen werden direkt in der Produktionsumgebung geprüft, bevor sie für alle live gehen.
- Secrets: Supabase-URL und Anon-Key als Umgebungsvariablen in Vercel; kein Service-Key im Frontend.
- Datenimport: BLS- und USDA-Nährwerte einmalig in Supabase importieren (Tabelle NutrientValue, nur lesend).
- Geplanter Job: einmal täglich löscht ein Supabase-Job Rezepte, deren deleted_at älter als 48 Stunden ist.
18. Open questions & assumptions
- Bestätigt: Die Gruppe hat unter 10 Personen.
- Bestätigt: Sprache ist Deutsch.
- Bestätigt: Nur der Admin verwaltet Einladungen; alle Mitglieder dürfen alle Rezepte bearbeiten.
- Bestätigt: Der Papierkorb ist für alle sichtbar; jedes Mitglied kann gelöschte Rezepte wiederherstellen.
- Bestätigt: Rezepte im Papierkorb werden nach 48 Stunden endgültig gelöscht.
- Bestätigt: Die Nährwerte stammen aus einem einmaligen BLS/USDA-Import; die Quelle je Zutat wird angezeigt.
- Bestätigt: Die Zutatensuche sucht nur nach dem Namen und zeigt rohe, unverarbeitete Zutaten.
- Bestätigt: Saison-Tab nur mit Rezepten der eigenen Gruppe, aktueller Monat automatisch, keine Suche, Gruppierung absteigend nach Anzahl Saisonzutaten, nicht hinterlegte Zutaten werden ignoriert.
- Bestätigt: Abgleich der Saison-Liste mit BLS/USDA-Namen ohne Groß-/Kleinschreibung und Leerzeichen am Rand, BLS-Vorrang.
- Bestätigt: Die Saison-Liste wird nur im Code gepflegt, ohne Oberfläche zur Pflege.
- Bestätigt: Die Saison-Liste hat keine Herkunftsangaben.
- Bestätigt: Pro Zutat sind mehrere Monatsbereiche erlaubt.
- Bestätigt: Bereiche über den Jahreswechsel sind erlaubt.