From fa4a4c9ef73f3c67f69a078a0f6d43ba2d88fa3f Mon Sep 17 00:00:00 2001 From: Marcel Raddatz Date: Thu, 9 Apr 2026 15:51:26 +0200 Subject: [PATCH] docs(specs): add J9 variety score config user journey and variety page rework spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Adds J9 (Configure variety score) to userjourneys.html — new journey for tuning the algorithm per household dietary context (e.g. disabling protein penalties for vegetarian households); introduces screen E4 (Variety settings) - Adds specs/frontend/variety-page-rework.html with 3 design variations for the /planner/variety page rework: recipe-name pills, action rows (recommended), and week-grid with side panel Co-Authored-By: Claude Sonnet 4.6 --- specs/frontend/variety-page-rework.html | 841 ++++++++++++ specs/userjourneys.html | 1606 +++++++++++++++++++++++ 2 files changed, 2447 insertions(+) create mode 100644 specs/frontend/variety-page-rework.html create mode 100644 specs/userjourneys.html diff --git a/specs/frontend/variety-page-rework.html b/specs/frontend/variety-page-rework.html new file mode 100644 index 0000000..d128314 --- /dev/null +++ b/specs/frontend/variety-page-rework.html @@ -0,0 +1,841 @@ + + + + + + Variety Page Rework · 3 Variationen + + + + + +
+ +
+
+

Variety Page — Rework

+

3 Design-Variationen · Route: /planner/variety

+
+
+ screen: C2
+ journey: J4
+ version: 1.0
+ date: 2026-04-09 +
+
+ +

+ Zwei Kernprobleme werden adressiert: (1) Warnungen zeigen aktuell Wochentag-Kürzel ("MON, WED") + statt Rezeptnamen — rein frontend-seitig lösbar über weekPlan.slots-Mapping. + (2) Es gibt keine Swap-Aktion direkt aus den Warnungen heraus. Das Protein-Score-Problem + für vegetarische Haushalte ist ein Backend-Thema und separat zu behandeln. +

+ +
+

Protein-Score: Vegetarische Haushalte — Backend TBD

+

+ Die aktuelle Formel proteinDiversity = 10 − repeats × 2 bestraft vegetarische + Proteinquellen (Tofu, Linsen, Ei) stärker als in omnivoren Haushalten üblich. + Frontend-seitig ändert sich das Label "Protein-Vielfalt" ggf. zu "Quellen-Vielfalt" sobald + das Backend die Score-Gewichtung anpasst. Bis dahin: keine Änderung an ScoreBreakdownList. +

+
+ + + + +
+
+
1
+
+
Rezept-Pills in Warnkarten
+
Minimale Änderung an der bestehenden Seitenstruktur. Warnkarten zeigen statt "MON, WED" konkrete Rezept-Pills mit Tauschen-Button. Seitenaufbau und Score-Hero bleiben identisch.
+ Vertraut · Geringer Aufwand +
+
+ +
+
+
Desktop
+
+
+
+ +
+
+ Planer + / + Abwechslungs-Analyse +
+
+ +
+
+
6.5/10
+
+
Verbesserbar
+
+
Bewertung im Detail
+
+
Quellen-Vielfalt6/10
+
Zutaten-Überlappung8/10
+
Aufwandsbalance9/10
+
+ +
Hinweise
+ +
+
Tofu mehrfach diese Woche
+
+ MoTofu-Curry + MiTofu-Bowl +
+
+ +
+
Linsen in mehreren Gerichten
+
+ DiLinsen-Suppe + FrLinsen-Dal +
+
+
+ +
+
Quellen-Verteilung
+
+
Mo
TOF
+
Di
LIN
+
Mi
TOF
+
Do
GEM
+
Fr
LIN
+
Sa
+
So
+
+
Aufwandsverteilung
+
+
+
+
+
+ Einfach ×3Mittel ×2 +
+
+
+
+
+
+
+
+ +
+
Mobile
+
+
+
+
Abwechslungs-Analyse
+
+
6.5/10
+
+
Verbesserbar
+
Hinweise
+
+
Tofu mehrfach diese Woche
+
+ MoTofu-Curry + MiTofu-Bowl +
+
+
+
Linsen in mehreren Gerichten
+
+ DiLinsen-Suppe + FrLinsen-Dal +
+
+
+
+
📅
Planer
+
🍽
Rezepte
+
🛒
Einkauf
+
⚙️
Einstellungen
+
+
+
+
+
+
+ +
+
Notizen
+
    +
  • Kein Backend-Change nötig. Frontend mappt tagRepeat.days[]weekPlan.slots.find(s => s.dayOfWeek === day)recipe.name
  • +
  • Pill-Swap-Button (↔): navigiert zu /planner?week={weekStart}&swap={slotId} — öffnet RecipePicker für den betreffenden Slot
  • +
  • Pill-Label links: Wochentag-Kürzel (Mo, Di, …) aus dayOfWeek-Mapping
  • +
  • Wenn ein Slot leer ist (Rezept wurde bereits entfernt): Pill zeigt nur den Wochentag, kein Swap-Button
  • +
  • Geringe Änderung: nur VarietyWarningCards.svelte + variety.ts anpassen; Rest der Seite bleibt
  • +
+
+
+ + + + +
+
+
2
+
+
Aktions-Zeilen
+
Warnungen stehen oben, Score-Hero wird kompakt. Pro Warnung gibt es eine vollständige Rezept-Zeile mit Wochentag und dediziertem "Tauschen"-Button. Fokus auf sofortige Handlung statt auf Metrik-Verständnis.
+ Empfohlen · Aktionsfokus +
+
+ +
+
+
Desktop
+
+
+
+ +
+
+ Planer + / + Abwechslungs-Analyse +
+
+ +
+
6.5/10
+
+
Verbesserbar — 2 Hinweise
+
+
+
+ +
+
+
Empfehlenswerte Tausche
+ + +
+
🔄
+
+
Tofu mehrfach diese Woche
+
+ Tofu-Curry· Montag + +
+
+ Tofu-Bowl· Mittwoch + +
+
+
+ + +
+
🔄
+
+
Linsen in mehreren Gerichten
+
+ Linsen-Suppe· Dienstag + +
+
+ Linsen-Dal· Freitag + +
+
+
+ + +
+ Bewertung im Detail ▾ +
+
Quellen-Vielfalt6/10
+
Zutaten-Überlappung8/10
+
Aufwandsbalance9/10
+
+
+
+ +
+
Quellen-Verteilung
+
+
Mo
TOF
+
Di
LIN
+
Mi
TOF
+
Do
GEM
+
Fr
LIN
+
Sa
+
So
+
+
+
+
+
+
+
+
+
+ +
+
Mobile
+
+
+
+
Abwechslungs-Analyse
+
+ +
+
6.5/10
+
Verbesserbar
+
+
Empfehlenswerte Tausche
+ +
+
🔄 Tofu mehrfach diese Woche
+
Tofu-Curry Mo
+
Tofu-Bowl Mi
+
+
+
🔄 Linsen in mehreren Gerichten
+
Linsen-Suppe Di
+
Linsen-Dal Fr
+
+
+
+
📅
Planer
+
🍽
Rezepte
+
🛒
Einkauf
+
⚙️
Einstellungen
+
+
+
+
+
+
+ +
+
Notizen
+
    +
  • Score-Hero wird kompakt: Zahl + Label + Balken in einer horizontal komprimierten Leiste oben
  • +
  • Sub-Scores in aufklappbarem <details>-Element — zugänglich, kein JavaScript nötig
  • +
  • Jeder "Tauschen"-Button navigiert zum Planer mit dem spezifischen Slot vorselektiert
  • +
  • Wochentag als ausgeschriebenes Wort ("Montag") — nicht Kürzel — für bessere Lesbarkeit
  • +
  • Mobile: Score-Hero bleibt kompakt oben, Action-Rows nehmen den Hauptraum ein
  • +
  • Größerer Aufwand als V1: VarietyWarningCards grundlegend neu strukturieren
  • +
+
+
+ + + + +
+
+
3
+
+
Wochenraster mit Kontext-Panel
+
Das bestehende Protein-Raster wird zum Haupt-Interface. Alle 7 Tage zeigen das vollständige Rezept. Problematische Slots sind gelb markiert — Klick öffnet das rechte Panel mit Erklärung und Swap-CTA.
+ Ambitiös · Meiste Übersicht +
+
+ +
+
+
Desktop
+
+
+
+ +
+
+ Planer + / + Abwechslungs-Analyse + +
+ Abwechslung + 6.5 + /10 +
+
+
+ +
+
Wochenübersicht — gelb markierte Gerichte haben Hinweise
+
+ +
+
Mo
+
Tofu-Curry
+
+ +
+
Di
+
Linsen-Suppe
+
+ +
+
Mi
+
Tofu-Bowl
+
+ +
+
Do
+
Gemüse-Stir-Fry
+
+ +
+
Fr
+
Linsen-Dal
+
+ +
+
Sa
+
+
+ +
+
So
+
+
+
+ +
Aufwandsverteilung
+
+
+
+
+
+ Einfach ×3Mittel ×2 +
+ +
+
Quellen-Vielfalt6/10
+
Zutaten-Überlappung8/10
+
Aufwandsbalance9/10
+
+
+ + +
+
+ 6.5 + /10 +
+
Tofu-Curry — Montag
+
Tofu taucht diese Woche auch am Mittwoch auf (Tofu-Bowl). Ein Tausch würde die Quellen-Vielfalt verbessern.
+
Andere betroffene Gerichte
+
+
Tofu-Bowl
Mittwoch
+
+ +
Öffnet den Rezept-Picker für Montag.
+
+
+
+
+
+
+
+ +
+
Mobile (Tab-Navigation)
+
+
+
+
Abwechslungs-Analyse6.5/10
+
+ +
+ + +
+ +
+
Tofu mehrfach diese Woche
+
Tofu-Curry Mo
+
Tofu-Bowl Mi
+
+
+
Linsen in mehreren Gerichten
+
Linsen-Suppe Di
+
Linsen-Dal Fr
+
+
+
+
📅
Planer
+
🍽
Rezepte
+
🛒
Einkauf
+
⚙️
Einstellungen
+
+
+
+
+
+
+ +
+
Notizen
+
    +
  • Wochenraster ersetzt das bisherige Protein-Grid (7 Spalten, Rezeptname statt Kürzel, größere Zellen)
  • +
  • Gelber Slot = mindestens ein Hinweis vorhanden. Klick selektiert den Slot, Panel rechts aktualisiert sich.
  • +
  • Panel zeigt: betroffenes Rezept + Wochentag + Erklärung + andere betroffene Slots + primären "Tauschen"-Button
  • +
  • Score-Zahl wandert in die Topbar-Leiste (kompakt, immer sichtbar)
  • +
  • Mobile: kein Panel — stattdessen Tab-Switcher "Übersicht | Hinweise (N)" mit aufklappbaren Einträgen
  • +
  • Größter Umbau: +page.svelte Struktur und alle beteiligten Komponenten müssen neu aufgebaut werden
  • +
+
+
+ + +
+

Maschinen-lesbare Spezifikation

+

Gilt für alle drei Variationen. Implementierungs-Details werden nach Variantenwahl konkretisiert.

+ +
+/* spec:rules — Variety Page Rework (alle Variationen)
+ *
+ * RECIPE NAME MAPPING (frontend, no backend change)
+ *   Source: weekPlan.slots[] → { dayOfWeek: "MON"|"TUE"|..., recipe: { id, name } }
+ *   tagRepeats[].days[] contains dayOfWeek keys (e.g. "MON")
+ *   slotsByDay = Object.fromEntries(weekPlan.slots.map(s => [s.dayOfWeek, s]))
+ *   recipeName = slotsByDay[day]?.recipe?.name ?? day
+ *   slotId = slotsByDay[day]?.id
+ *
+ * SWAP NAVIGATION
+ *   "Tauschen" button href: /planner?week={weekStart}&swap={slotId}
+ *   weekStart available in page data
+ *   slotId from weekPlan.slots mapping above
+ *   Opens RecipePicker for that slot (existing functionality in planner page)
+ *
+ * DAY LABEL MAPPING (for display)
+ *   MON → "Montag"  TUE → "Dienstag"  WED → "Mittwoch"  THU → "Donnerstag"
+ *   FRI → "Freitag" SAT → "Samstag"   SUN → "Sonntag"
+ *   Short: Mo, Di, Mi, Do, Fr, Sa, So
+ *
+ * EMPTY SLOT HANDLING
+ *   If slotsByDay[day] is undefined: show day key only, no swap button
+ *   This can happen if slot was deleted since varietyScore was computed
+ *
+ * PROTEIN SCORE — VEGETARIAN NOTE
+ *   Label "Protein-Vielfalt" in ScoreBreakdownList may change to "Quellen-Vielfalt"
+ *   pending backend decision on scoring weight adjustment.
+ *   No frontend change required until backend ships the updated score.
+ *
+ * VARIATION-SPECIFIC
+ *   V1: Modify VarietyWarningCards + Warning type (add slots: { day, recipeName, slotId }[])
+ *       computeWarnings() now returns slots[] instead of string days[]
+ *   V2: Restructure VarietyWarningCards to ActionRows; VarietyScoreHero → compact variant
+ *       
for sub-scores (no JS needed) + * V3: Replace protein grid with full week grid (recipe names); add side panel component + * Mobile: tab switcher (Übersicht | Hinweise) using $state activeTab + */ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValueNotes
Shared: Recipe Mapping
data-sourceweekPlan.slots[].dayOfWeek + recipealready in page data
swap-url/planner?week={weekStart}&swap={slotId}RecipePicker pre-selects slot
day-longMON→Montag, TUE→Dienstag…for V2 display
day-shortMON→Mo, TUE→Di…for V1 pills + V3 grid
V1 Recipe Pills
pill-padding5px 10px 5px 12pxleft more for text
swap-btn-size22×22px, border-radius 50%within pill
pill-bgwhite, border --yellow-lighton yellow-tint card
V2 Action Rows
score-compact-height~64pxreplaces 180px hero
details-summarynative <details>, no JSsub-scores hidden by default
recipe-row-bg--color-subtlewithin white action card
V3 Week Grid
slot-height52px minenough for 2-line recipe name
warn-slot-ring2px solid --yellow + yellow-tint bgproblem indicator
selected-slot-ring2px solid --green-darkactive selection
panel-width280pxfixed, right side
mobile-tab-active-bg--green-darkselected tab button
+
+ +
+ + diff --git a/specs/userjourneys.html b/specs/userjourneys.html new file mode 100644 index 0000000..be8458d --- /dev/null +++ b/specs/userjourneys.html @@ -0,0 +1,1606 @@ + + + + + + Recipe App — User Journeys v1.0 + + + + + + + +
+ + +
+
+

User journeys

+

Recipe app · Eight core journeys · Planner & household member roles

+
+
+ locked
+ Version: 1.2
+ Last updated: 2026-04
+ Journeys: 9
+ Roles: planner · household member +
+
+ + +
+
All journeys at a glance
+

The app serves two user roles. The planner (you) has full access — adding recipes, building the weekly plan, generating the shopping list, and managing the household. The household member (your partner, other household members) has read-only access to the plan and collaborative access to the shopping list. Journeys J7 and J8 cover post-onboarding household management: adding or removing members and keeping the pantry staples configuration current. J9 covers tuning the variety score algorithm to match the household's dietary context (e.g. disabling meat-centric protein penalties for a vegetarian household).

+ +
+
+
+
J1
+
Add a recipe
+
+
Save a recipe from memory, a cookbook, or improvisation into the app library with ingredients and tags.
+
Planner only
+
+
+
+
J2
+
Plan the week
+
+
Assign meals to days, get suggestions that avoid ingredient repetition, review the variety score, and confirm the plan.
+
Planner only
+
+
+
+
J3
+
Cook tonight
+
+
Check what's for dinner, open the recipe, cook step-by-step, and mark the meal as cooked to update variety tracking.
+
Planner only
+
+
+
+
J4
+
Adapt on the fly
+
+
When plans change mid-week, quickly swap a meal for a low-effort alternative and keep the week on track.
+
Planner only
+
+
+
+
J5
+
Generate shopping list
+
+
Turn the confirmed week plan into a live shared shopping list — filtered for pantry staples. Anyone can add or remove items anytime.
+
Planner generates · Household shops
+
+
+
+
J6
+
Household setup
+
+
One-time setup: create the planner account, configure pantry staples, invite household members, and confirm access levels.
+
Planner creates · Members join
+
+
+
+
J7
+
Manage members
+
+
Invite new household members post-setup or revoke access. Keep the household roster current as people join or leave.
+
Planner manages · Members join
+
+
+
+
J8
+
Edit staples
+
+
Update which pantry ingredients are always on hand. Changes take effect on the next generated shopping list.
+
Planner only
+
+
+
+
J9
+
Configure variety score
+
+
Tune the variety algorithm to the household's dietary context — disable protein-type penalties for vegetarian households or adjust how heavily ingredient overlaps are weighted.
+
Planner only
+
+
+
+ + + +
+
+
J1
+
+
Journey 1
+
Add a recipe
+
The planner saves a recipe into the app — from memory, a physical cookbook, or improvisation. Tags are applied so the planner and suggestion engine can use the recipe intelligently in future planning.
+
+
+
Actor
+
Planner
+
+
+
Frequency
+
Occasional — as new recipes are discovered
+
+
+
Entry point
+
Recipe library (B1) or + button in nav
+
+
+
+
+
+
+
+
+
B1
+
Open library
+
Recipe list view
+
+
+
+
B3
+
Add recipe
+
Name + ingredients
+
+
+
+
B3
+
Add steps
+
Cooking instructions
+
+
+
+
B3
+
Tag it
+
Effort, protein, child-friendly
+
+
+
+
+
Saved
+
In library
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepWhat happensScreenNotes
Open libraryPlanner taps Recipes in nav or the + button anywhere in the app.B1Entry from nav or from the planner (C1) when a day has no meal assigned.
Add recipe formPlanner enters recipe name, serves count, and adds ingredients one by one with name and quantity.B3B3 is a single form used for both add and edit states. Form is prefilled when editing.
Add cooking stepsPlanner adds numbered steps in free text. Steps are used in cook mode (B4).B3Steps are optional at save time — a recipe without steps can still be planned and cooked from ingredient list only.
Tag the recipePlanner selects tags: effort level (easy / medium / hard), child-friendly (yes/no), primary protein or category (chicken, fish, vegetarian, pasta, etc.).B3Tags are used by the suggestion engine in J2 to avoid repetition. Minimum: effort + one category tag required to save.
SaveRecipe is saved and appears in the library (B1). Planner is returned to B1 or to wherever they came from.B1If entered from a day slot in the planner, the recipe is optionally offered for that day immediately after saving.
+
+
+
Design notes
+
    +
  • B3 and B4 (add and edit recipe) share one form component — the only difference is the initial state (empty vs prefilled).
  • +
  • Tags drive intelligent suggestions. The more recipes are tagged, the better the variety algorithm performs.
  • +
  • Recipes from memory or physical cookbooks are the primary source — the app makes no assumptions about digital import.
  • +
+
+
+
+ + + +
+
+
J2
+
+
Journey 2
+
Plan the week
+
The planner builds the dinner plan for the coming week. The app suggests recipes that avoid repeating ingredients from recent meals, balances effort across days, and scores variety so the planner can confirm or adjust before the week begins.
+
+
+
Actor
+
Planner
+
+
+
Frequency
+
Weekly — typically at the weekend
+
+
+
Entry point
+
Planner (C1) — default home screen
+
+
+
+
+
+
+
+
+
C1
+
Open planner
+
7-day grid view
+
+
+
+
C2
+
Get suggestions
+
Filtered by variety
+
+
+
+
C1
+
Fill day slots
+
Pick or drag meals
+
+
+
+
C3
+
Review variety
+
Ingredient overlap score
+
+
+
+
?
+
Swap needed?
+
Optional adjustment
+
+
+
+
+
Week confirmed
+
Plan locked
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepWhat happensScreenNotes
Open plannerPlanner opens the app. The weekly planner is the default home screen showing the current week with any already-planned meals.C1Today's slot is always highlighted in yellow. Empty slots show a dashed + prompt.
Get suggestionsPlanner taps an empty day slot or the suggestions button. The app shows recipes filtered to avoid ingredients used in the past 3 days and the same protein as adjacent days.C2Suggestions also balance effort — if the previous two days were hard meals, easy meals are surfaced first.
Fill day slotsPlanner picks a suggestion or manually selects a recipe from the library for each day.C1Saturday is optional — some weeks have no planned meal on Saturday. Empty slots are valid.
Review variety scoreThe variety score (0–10) updates live as meals are added. It reflects ingredient overlap across the week. Warnings surface for specific repeated ingredients.C3 C1Score is visible at all times on C1 (variety banner on mobile/tablet, sidebar widget on desktop). C3 shows the full breakdown.
Swap a meal (optional)If the variety score is low or a specific warning appears, the planner swaps one meal for an alternative suggestion.C2Swap uses the same suggestion engine as the initial fill. Swapping updates the score immediately.
Confirm the weekPlanner confirms the plan. The week is locked and visible (read-only) to household members. This also triggers the option to generate a shopping list (J5).C1Confirming does not prevent future edits — the planner can still swap meals mid-week via J4.
+
+
+
Design notes
+
    +
  • The variety score is the central metric of the app — it must be visible throughout this entire journey without extra navigation.
  • +
  • The suggestion filter considers: ingredients used in the last 3 days, same-protein consecutive days, and effort balance. Recipe tags (from J1) power all three filters.
  • +
  • Household members can see the confirmed plan as read-only immediately after confirmation.
  • +
+
+
+
+ + + +
+
+
J3
+
+
Journey 3
+
Cook tonight
+
The planner checks what's for dinner, opens the recipe, and cooks using the step-by-step cook mode. Marking the meal as cooked logs it to the variety history, which feeds back into next week's suggestions.
+
+
+
Actor
+
Planner
+
+
+
Frequency
+
Daily — used at the stove
+
+
+
Entry point
+
Planner (C1) — today highlight
+
+
+
Context
+
Mobile, hands busy, kitchen environment
+
+
+
+
+
+
+
+
+
C1
+
Check today
+
Tonight's meal highlighted
+
+
+
+
B2
+
Open recipe
+
Ingredients + steps
+
+
+
+
B4
+
Cook mode
+
Step-by-step, big text
+
+
+
+
+
Mark cooked
+
Logged to history
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepWhat happensScreenNotes
Check todayPlanner opens the app. Today's slot is highlighted in yellow on the planner. The meal name is visible without any tap.C1The today highlight is the most important element on C1. It must be visible on first render with zero interaction.
Open recipePlanner taps the today slot. The recipe detail screen shows the full ingredient list and step count.B2B2 shows ingredients scaled to the saved serving count. No serving adjustment is required in this journey.
Enter cook modePlanner taps "Cook now". The screen switches to full-screen cook mode with one step visible at a time in large, readable text. Screen stays awake.B4B4 is designed for kitchen use: 16px body text, 1.75 line height, single step per screen, tap-anywhere to advance. Screen wake lock is requested.
Mark as cookedOn the final step, the planner taps "Done". The meal is logged to cooking history with today's date.B4C1The cooking log is the data source for the variety algorithm. Meals cooked more recently are weighted more heavily in the repetition filter.
+
+
+
Design notes
+
    +
  • Cook mode (B4) is a high-stakes screen — the user is standing at a stove with wet hands. It must be operable with one tap and no fine motor precision required.
  • +
  • Screen wake lock prevents the phone from sleeping during cooking. This should be requested on entering B4 and released on exit.
  • +
  • The "mark as cooked" action is the feedback loop that makes J2 smarter over time. It should feel lightweight, not like admin work.
  • +
+
+
+
+ + + +
+
+
J4
+
+
Journey 4
+
Adapt on the fly
+
Plans change. A busy evening, a missing ingredient, or a child who won't eat what was planned triggers a mid-week swap. The app suggests low-effort alternatives and updates the plan instantly.
+
+
+
Actor
+
Planner
+
+
+
Frequency
+
1–2× per week typically
+
+
+
Entry point
+
Planner (C1) — any day slot
+
+
+
Urgency
+
High — decision needed quickly
+
+
+
+
+
+
+
+
+
C1
+
Plan changes
+
Tap day slot
+
+
+
+
C2
+
Quick swap
+
Low-effort alternatives
+
+
+
+
C1
+
Pick alternative
+
Confirm new meal
+
+
+
+
+
Plan updated
+
History logged
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepWhat happensScreenNotes
Trigger swapPlanner taps a meal slot and selects "Swap meal". The original meal is not yet removed — the swap is a preview.C1The "Swap" button is visible inline in the upcoming list on mobile and in the detail panel on desktop — one tap away at all times.
View quick alternativesThe suggestion screen shows 3–5 low-effort alternatives that avoid the ingredients already used that week. Sorted: easiest first.C2When the swap is triggered mid-week (today or a past day), effort filter defaults to Easy. The variety filter still applies.
Confirm new mealPlanner picks an alternative. The day slot updates immediately. Variety score recalculates.C1If no suitable suggestion exists, the planner can manually select any recipe from the library.
History loggedThe swap is logged — both the original meal (not cooked) and the replacement. This is used to ensure the original recipe isn't over-suppressed in future suggestions.The original uncooked meal remains in the library and can be planned for a future week.
+
+
+
Design notes
+
    +
  • Speed is critical in this journey — the user is making a decision under time pressure. The swap flow should never exceed 3 taps from the moment "Swap" is tapped to the plan being updated.
  • +
  • Alternatives are sorted by effort (easiest first) because mid-week swaps typically happen because the original plan was too ambitious for that day.
  • +
  • The variety score updates immediately after confirmation, giving the planner instant feedback on whether the swap improved or worsened the week's balance.
  • +
+
+
+
+ + + +
+
+
J5
+
+
Journey 5
+
Generate shopping list
+
Once the week is confirmed, a shopping list is generated from all meal ingredients. Pantry staples are automatically filtered out. The list is immediately live and shared with all household members. Anyone can add or remove items at any time.
+
+
+
Actors
+
Planner generates · Household shops
+
+
+
Frequency
+
Weekly — after plan confirmation
+
+
+
Entry point
+
Shopping tab (D1) or prompt after J2
+
+
+
+
+
+
+
+
+
C1
+
Week confirmed
+
Plan locked in
+
+
+
+
D1
+
Collect ingredients
+
All 7 meals merged
+
+
+
+
D1
+
Smart filter
+
Remove staples
+
+
+
+
+
List is live
+
Shared with household immediately
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepWhat happensScreenRole
Collect ingredientsAll ingredients from all planned meals are gathered. Shared ingredients across meals are merged and quantities summed (e.g. 3 + 2 carrots = 5 carrots).D1Planner
Smart filterPantry staples (olive oil, salt, pasta, rice, etc.) defined by the planner in settings are automatically removed from the list.D3Planner
List goes liveThe generated list is immediately live and visible to all household members. No approval step needed.D1Both roles
Shop collaborativelyAny household member can check off items while shopping. Checked items stay checked for all members — no double buying.D1Household member
Add itemsHousehold members can add items not on the generated list (e.g. household supplies, snacks). These appear at the bottom of the list.D1Both roles
+
+
+
Design notes
+
    +
  • Only the planner can generate the list. All household members can view, check off, add, and remove items. The list is always live — no approval or publishing step.
  • +
  • Checked items stay checked for everyone — this prevents double-buying when multiple family members are shopping simultaneously or at different times.
  • +
  • The smart filter (D3) is configured once during onboarding (J6, step A3) and can be updated at any time from settings. The planner's staples list grows over time.
  • +
  • CalDAV export is planned as a future enhancement (E3 Integrations) — not part of v1. The in-app shared list is the primary collaboration mechanism.
  • +
+
+
+
+ + + +
+
+
J6
+
+
Journey 6
+
Household setup
+
A one-time journey completed when the app is first used. The planner creates an account, names the household, defines pantry staples, and invites household members. Members accept the invite and gain access to the meal plan and shopping list.
+
+
+
Actors
+
Planner creates · Members join
+
+
+
Frequency
+
Once — on first use
+
+
+
Entry point
+
A1 Welcome screen (new user)
+
+
+
+
+
+
+
+
+
A1
+
Welcome
+
Sign up
+
+
+
+
A2
+
Household setup
+
Name the household
+
+
+
+
A3
+
Staples setup
+
Define pantry defaults
+
+
+
+
A2
+
Invite members
+
Send link or code
+
+
+
+
A4
+
Member joins
+
Accepts invite
+
+
+
+
+
Access granted
+
Household ready
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepWhat happensScreenRole
Create accountPlanner signs up with email and password. The account is created with the Planner role automatically assigned.A1Planner
Name the householdPlanner gives the household a name (e.g. "Smith family"). This name appears in the sidebar on desktop and in the app header.A2Planner
Define pantry staplesPlanner selects which ingredients their household always has on hand. These are excluded from generated shopping lists. A default list of common staples is pre-selected and can be adjusted.A3Planner
Invite household membersPlanner sends an invite link or code to household members (e.g. spouse). One invite per member. The invite grants Household Member role on acceptance.A2Planner
Member accepts inviteThe invited person opens the link, creates an account, and is automatically joined to the household with the Member role.A4Household member
Access grantedThe member can now see the meal plan (read-only) and the shopping list (view, check off, add items). The planner retains full access.C1 D1Both roles
+
+
+
Design notes
+
    +
  • A3 (staples setup) and D3 (staples manager in settings) are the same component — set up once in onboarding and editable at any time from settings.
  • +
  • The invite mechanism uses a link or short code — no email-based invite system is required in v1. The planner shares the link via any messaging app.
  • +
  • Role summary: Planner has full access to all 18 screens. Household member has read-only access to C1 (weekly planner) and collaborative access to D1 (shopping list). No other screens are accessible to household members in v1.
  • +
  • Future: child accounts with view-only access to the meal plan are planned but not scoped for v1.
  • +
+
+
+
+ + + +
+
+
J7
+
+
Journey 7
+
Manage household members
+
After the initial setup, the planner may need to invite additional members or revoke access for someone who has left the household. The members page provides a live overview of who is in the household, their role, and invite status.
+
+
+
Actors
+
Planner (invites · removes) · New member (accepts)
+
+
+
Frequency
+
Rare — when household composition changes
+
+
+
Entry point
+
Members page (E2) via settings nav
+
+
+
+
+
+
+
+
+
E2
+
Open members
+
See household roster
+
+
+
+
E2
+
Invite member
+
Generate link or code
+
+
+
+
A4
+
Member accepts
+
Creates account
+
+
+
+
+
Access granted
+
Visible in roster
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepWhat happensScreenRole
Open members pagePlanner navigates to the Members page from the settings nav. The page lists all current household members with their name, role (Planner / Member), and join date. Pending invites are shown separately with their expiry status.E2Planner
Invite a new memberPlanner taps "Mitglied einladen". An invite link or short code is generated and displayed. The planner copies it and sends it via any messaging app (WhatsApp, SMS, email). No email delivery system is required — the link is the mechanism.E2Planner
Member accepts inviteThe invited person opens the link on their device, creates an account if they don't have one, and is automatically added to the household with the Household Member role. The planner sees the new member appear in the roster without refreshing.A4Household member
Access grantedThe new member can now see the weekly meal plan (read-only) and the shopping list (view, check off, add items). Their name appears in the member list on E2.C1 D1Both roles
Remove a memberPlanner taps a member's row and selects "Zugang entziehen". After an explicit confirmation prompt showing the member's name, the member is removed. They lose all access immediately. Their account is not deleted — they simply leave the household.E2Planner
+
+
+
Design notes
+
    +
  • J7 is the post-onboarding continuation of the J6 invite step — same A4 acceptance mechanism, different entry point (E2 not A2). The invite component is re-used.
  • +
  • Pending invites must show a clear expiry state. Expired invites should be re-generatable with one tap — the planner should not need to go through the full invite flow again.
  • +
  • Removing a member is a destructive, irreversible action. Require an explicit confirmation ("Zugang für [Name] wirklich entziehen?") to prevent accidental removal.
  • +
  • Household members can view E2 in read-only mode — they see who is in the household but cannot invite or remove anyone.
  • +
  • The planner cannot remove themselves — the Planner role must always have at least one person. Household role transfer is out of scope for v1.
  • +
+
+
+
+ + + +
+
+
J8
+
+
Journey 8
+
Edit pantry staples
+
The planner's pantry changes over time — a new dietary preference, a bulk buy, or a noticed pattern on the shopping list triggers a staple update. This journey lets the planner keep their "always on hand" list accurate so generated shopping lists stay useful.
+
+
+
Actor
+
Planner only
+
+
+
Frequency
+
Occasional — after household dietary or pantry changes
+
+
+
Entry point
+
Settings (E1) → Staples section (D3)
+
+
+
+
+
+
+
+
+
E1
+
Open settings
+
Settings hub
+
+
+
+
D3
+
Open staples
+
Browse categories
+
+
+
+
D3
+
Toggle items
+
Add or remove staples
+
+
+
+
+
Staples updated
+
Next list reflects changes
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepWhat happensScreenNotes
Open settingsPlanner navigates to the Settings page (E1) from the settings nav. The settings hub provides access to profile information and pantry staples configuration.E1E1 is the entry hub for settings-area screens. The Staples section is the most common destination from here and should be prominently placed.
Open staples managerPlanner taps the Staples section. The same StaplesManager component from onboarding (A3) renders in settings context — no sidebar, no "Weiter" navigation, just the ingredient category list.D3D3 = A3. One component, two render contexts (onboarding and settings). Context is passed as a prop — no duplicate component needed.
Browse and togglePlanner browses ingredient categories. Checked items are staples and will be excluded from shopping lists. Unchecked items will appear on the next generated list. Changes are saved automatically on each toggle — no save button required.D3Auto-save on toggle is required. The planner must never lose a change because they forgot to tap a save button mid-browsing.
Changes appliedThe updated staple configuration is persisted immediately. The next time a shopping list is generated (J5), the new staple set is used to filter out always-on-hand ingredients.Changes do not retroactively update an already-generated shopping list. If the current list should reflect the change, the planner must regenerate it via J5.
+
+
+
Design notes
+
    +
  • D3 and A3 are the same component with two render contexts. The onboarding context includes the progress sidebar and navigation footer. The settings context renders the staples list standalone — no onboarding chrome.
  • +
  • Trigger for this journey: the planner notices an item on their shopping list they always have at home, or a missing item they now always keep stocked. This is a fast corrective action — optimise for speed, not discoverability.
  • +
  • No confirmation required for staple toggles — they are low-stakes and instantly reversible. Auto-save on change is the correct pattern.
  • +
  • Consider a direct "Vorräte bearbeiten" shortcut link on the shopping list page (D1) — the most common trigger for this journey is noticing a wrong staple while looking at the list.
  • +
+
+
+
+ + + + +
+
+
J9
+
+
Journey 9
+
Configure variety score
+
The variety algorithm ships with defaults designed for omnivore households — protein-type tags penalise consecutive repeats and ingredient overlaps reduce the score. A vegetarian or vegan household will find these defaults unfair: tofu, eggs, and legumes repeat because there are simply fewer protein sources available. This journey lets the planner tune the algorithm to their household's dietary reality without any score gaming.
+
+
+
Actor
+
Planner only
+
+
+
Frequency
+
Rare — once when dietary context changes
+
+
+
Entry point
+
Settings (E1) → Variety settings card (E4)
+
+
+
Trigger
+
Score feels persistently unfair or misleading
+
+
+
+
+
+
+
+
+
E1
+
Open settings
+
Settings hub
+
+
+
+
E4
+
Open variety settings
+
Current config visible
+
+
+
+
E4
+
Toggle tag types
+
Protein on / off
+
+
+
+
?
+
Adjust weights?
+
Optional fine-tuning
+
+
+
+
C3
+
Review impact
+
Updated score
+
+
+
+
+
Config saved
+
Persisted per household
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepWhat happensScreenNotes
Open settingsPlanner navigates to Settings (E1). The settings hub now shows a third card: "Vielfalt-Einstellungen". Current score is shown as a stat number on the card so the planner knows what they are about to tune.E1Planner role only. Household members cannot see the Vielfalt-Einstellungen card. The card is added to the E1 settings hub grid alongside Vorräte and Haushalt cards.
Open variety settingsPlanner taps the card. Screen E4 shows the full algorithm config: which tag types trigger repeat warnings (default: Protein, Küche) and the penalty weights for each violation type.E4E4 shows the current household config. If no custom config has been saved, defaults are displayed: Protein ✓, Küche ✓; all weights at "Mittel". A "Zurücksetzen auf Standard" link is always visible.
Toggle tag type checksPlanner toggles "Protein" off. For a vegetarian household, removing the protein check means tofu, eggs, and legumes appearing on consecutive days no longer reduces the variety score. The change auto-saves immediately.E4Each tag type in the household's recipe library can be checked or unchecked. Only types that actually appear in tagged recipes are listed — empty types are hidden. At least one type must remain checked; the toggle is disabled if it would leave zero checked types.
Adjust penalty weights (optional)Planner uses segmented controls (Niedrig / Mittel / Hoch) to tune how severely each violation type reduces the score. For example, reducing ingredient overlap weight to "Niedrig" for households that cook mostly single-ingredient dishes.E4Four weights are tunable: Tag-Wiederholung (default Mittel = 1.5 pts), Zutaten-Überschneidung (default Niedrig = 0.3 pts), Letzte Wochen (default Mittel = 1.0 pts), Doppelte Rezepte (default Hoch = 2.0 pts). Changes auto-save on interaction — no save button.
Review updated scorePlanner navigates back to the variety review page (C3). The score and all warning cards now reflect the updated config. Warnings for the disabled tag type no longer appear.C3The variety score shown on C1 (the planner home screen) also updates the next time the plan is loaded or a recipe is swapped. No full page reload is required on C3 — the server recalculates using the persisted config on each request.
Reset to defaults (optional exit)If the planner wants to undo all changes, they tap "Zurücksetzen auf Standard" at the bottom of E4. A confirmation prompt names the specific values that will be reset. On confirm, the household config is deleted and the system defaults are restored.E4Reset is a destructive action — it deletes the household's custom VarietyScoreConfig row. Confirmation dialog is required. Unlike most auto-save interactions, this one needs an explicit confirm because it discards all customisations at once.
+
+
+
Design notes
+
    +
  • The protein check is the primary motivation for this journey. Default it to OFF for households whose recipe library contains only vegetarian/vegan protein tags — consider detecting this automatically on first variety score load and surfacing a one-tap "Protein-Prüfung deaktivieren?" nudge on C3.
  • +
  • Penalty weights use three presets (Niedrig / Mittel / Hoch) rather than numeric sliders. Planners should not need to understand the backend scoring formula. Presets translate to fixed multipliers: Niedrig = ×0.5 of default, Mittel = ×1.0, Hoch = ×1.5.
  • +
  • Auto-save on every toggle/segmented-control change follows the same pattern as D3 staples. No save button. The "Zurücksetzen auf Standard" action is the only one that requires a confirmation step.
  • +
  • E4 is a settings screen, not a planning tool — it lives under E1, not under C3. The planner should access it deliberately, not accidentally while checking their variety score. However, C3 should surface a "Einstellungen anpassen →" link when the score has been consistently low for 3+ consecutive weeks.
  • +
  • Backend: config is stored per household in VarietyScoreConfig. PATCH /v1/households/mine/variety-config updates the config; DELETE resets to defaults. The variety score endpoint already reads from VarietyScoreConfig per request — no further backend work needed to make tuned configs take effect.
  • +
+
+
+
+ +
+ + + + +
+ +

Machine-readable spec — User journeys

+

This section is the authoritative journey reference for all agentic LLM tasks. Use it to understand which pages are involved in each journey, who performs each step, and what the key constraints are before building any screen or component.

+ +
/* Journey rules for agents
+ * 1.  Two roles exist: PLANNER (full access) and HOUSEHOLD_MEMBER (limited access).
+ * 2.  PLANNER can access: all screens (A1–E4).
+ * 3.  HOUSEHOLD_MEMBER can access: C1 (read-only) and D1 (view + check off + add items).
+ * 4.  The variety score must be visible on C1 at all times — it is not a secondary feature.
+ * 5.  J1 and J2 are preconditions for J5 — a shopping list requires planned meals with tagged recipes.
+ * 6.  J6 is a precondition for J5 shared list — household members must be invited before the list is shared.
+ * 7.  J3 "mark as cooked" feeds variety history which filters J2 suggestions. This feedback loop is critical.
+ * 8.  J4 swap must complete in ≤ 3 taps from "Swap" to updated plan.
+ * 9.  A3 and D3 are the same component (staples) — design and build once, reference from two entry points.
+ * 10. B3 and B4 (add + edit recipe) are the same form — build once with two initial states (empty vs prefilled).
+ * 11. The shopping list (D1) is real-time shared — checked items update for ALL household members instantly.
+ * 12. CalDAV export is future scope (E3) — do not build in v1.
+ * 13. Child accounts are future scope — do not design for in v1.
+ * 14. J7 is the post-setup continuation of J6 invite step — same A4 acceptance mechanism, different entry point (E2 not A2). The invite component is shared.
+ * 15. J8 entry is E1 (settings hub) → D3 (staples). D3 = A3: same component, settings context prop removes onboarding chrome (sidebar + nav footer).
+ * 16. Staple changes (J8) do not retroactively update an already-generated shopping list — planner must regenerate via J5 if the current list should reflect the change.
+ * 17. PLANNER cannot remove themselves from the household. Household role transfer is future scope, not v1.
+ * 18. J9 variety config is per-household and persisted in VarietyScoreConfig. Auto-save on toggle/weight change; reset-to-defaults requires a confirmation dialog. HOUSEHOLD_MEMBER cannot access E4.
+ * 19. J9 "Protein" tag-type toggle is the primary use case. Vegetarian households should disable it so tofu/eggs/legumes are not penalised for consecutive-day repetition.
+ * 20. E4 weight presets map to: Niedrig = ×0.5, Mittel = ×1.0 (default), Hoch = ×1.5 of the backend default weight.
+ */
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
JourneyTitleActor(s)Screens touched (in order)Key constraint
J1Add a recipePLANNERB1 → B3 → B1Minimum tags required: effort + 1 category. Tags power J2 suggestions.
J2Plan the weekPLANNERC1 → C2 → C1 → C3 → C1 (→ C2 if swap needed)Variety score must be visible throughout. Suggestions filter on: last 3 days ingredients, same-protein consecutive days, effort balance.
J3Cook tonightPLANNERC1 → B2 → B4 → C1Cook mode (B4): 16px body text, 1.75 line-height, one step per screen, screen wake lock, tap-anywhere to advance.
J4Adapt on the flyPLANNERC1 → C2 → C1Max 3 taps from Swap button to plan updated. Suggestions sorted by effort (easiest first) when triggered mid-week.
J5Generate shopping listPLANNER (generate) + HOUSEHOLD_MEMBER (shop)C1 → D1 (always live)Ingredients merged + summed across meals. Staples filtered (D3 config). Planner generates. List is always live — all members can view, check off, add, and remove items. Checked state persists for all users.
J6Household setupPLANNER (creates) + HOUSEHOLD_MEMBER (joins)A1 → A2 → A3 → A2 → [invite] → A4One-time journey. A3 = D3 (same component). Invite via link/code (no email system). Member role grants: C1 read-only + D1 collaborative.
J7Manage household membersPLANNER (manages) + HOUSEHOLD_MEMBER (accepts)E2 → [invite link] → A4 → E2Post-onboarding companion to J6 invite step. One-tap re-generation for expired invite links. Member removal requires explicit confirmation with member name. PLANNER cannot remove themselves.
J8Edit pantry staplesPLANNERE1 → D3Auto-save on toggle — no save button. Changes apply to next J5 shopping list generation only, not retroactively. D3 = A3 (same component, settings context prop).
J9Configure variety scorePLANNERE1 → E4 → C3Auto-save on every toggle/weight change. Reset-to-defaults requires explicit confirmation. Protein tag-type toggle is the primary use case for vegetarian households. Config is stored per household — changes take effect on next variety score request, no plan changes required.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ScreenNameJourneysPlanner accessMember access
A — Onboarding & auth
A1Welcome / sign upJ6FullFull (joining only)
A2Household setup + inviteJ6FullNo access
A3Staples setup (= D3)J6, J5FullNo access
A4Join household (accept invite)J6N/AFull
B — Recipe library
B1Recipe libraryJ1, J2FullNo access
B2Recipe detailJ3FullNo access
B3Add / edit recipe (one form, two states)J1FullNo access
B4Cook modeJ3FullNo access
C — Meal planning
C1Weekly plannerJ2, J3, J4, J5FullRead-only
C2Meal suggestionsJ2, J4FullNo access
C3Variety reviewJ2FullNo access
D — Shopping list
D1Shopping list (live shared)J5FullView + check off + add items
D3Staples manager (= A3)J5, J6, J8FullNo access
E — Settings
E1Settings hubJ8, J9FullNo access
E2Household (members + roles)J6, J7FullView-only
E3Integrations (CalDAV — future)FullNo access
E4Variety settings (tag types + weights)J9FullNo access
+ +
+ + + + \ No newline at end of file