From b36d4c731d4ef937d1a410d6309df90fd9153435 Mon Sep 17 00:00:00 2001 From: Marcel Raddatz Date: Thu, 2 Apr 2026 12:17:47 +0200 Subject: [PATCH] Add frontend journey specs with visual previews and LLM instructions Six self-contained HTML documents, one per user journey, each combining mobile/desktop previews with machine-readable implementation guides: - j1-add-recipe.html (B1, B3) - j2-plan-the-week.html (C1, C2, C3) - j3-cook-tonight.html (B2, B4) - j4-adapt-on-the-fly.html (swap trigger, C2 swap) - j5-shopping-list.html (D1) - j6-household-setup.html (A1, A2, A3/D3, A4) Co-Authored-By: Claude Opus 4.6 --- specs/frontend/j1-add-recipe.html | 394 ++++++++ specs/frontend/j2-plan-the-week.html | 1085 +++++++++++++++++++++++ specs/frontend/j3-cook-tonight.html | 395 +++++++++ specs/frontend/j4-adapt-on-the-fly.html | 295 ++++++ specs/frontend/j5-shopping-list.html | 389 ++++++++ specs/frontend/j6-household-setup.html | 472 ++++++++++ 6 files changed, 3030 insertions(+) create mode 100644 specs/frontend/j1-add-recipe.html create mode 100644 specs/frontend/j2-plan-the-week.html create mode 100644 specs/frontend/j3-cook-tonight.html create mode 100644 specs/frontend/j4-adapt-on-the-fly.html create mode 100644 specs/frontend/j5-shopping-list.html create mode 100644 specs/frontend/j6-household-setup.html diff --git a/specs/frontend/j1-add-recipe.html b/specs/frontend/j1-add-recipe.html new file mode 100644 index 0000000..c9d50f1 --- /dev/null +++ b/specs/frontend/j1-add-recipe.html @@ -0,0 +1,394 @@ + + + + + + J1 — Add a Recipe + + + + +
+ +
+
J1
+

Add a recipe

Save recipe with ingredients, steps, tags, and hero image.

B1 → B3 → B1 · Planner · Min: effort + 1 category tag
+
+ + +
+

Recipe library

B1
+
Browse all recipes. Desktop: app sidebar + topbar with search bar and filter chips + 4-column card grid. The grid fills the content area naturally — not wrapped in an additional card or panel.
+
V2 · Card grid — mobile 2-col, desktop sidebar + 4-col with filters
+ +
+
+
Mobile · 320px
+
+
9:41●●● WiFi 🔋
+
+
Recipes
🔍
+
+
+
+
🍝
Tomato pasta
45 min · Easy
+
🍗
Chicken stir-fry
25 min · Easy
+
🐟
Salmon teriyaki
35 min · Medium
+
🍄
Mushroom risotto
50 min · Medium
+
+
+
📅
Planner
📖
Recipes
🛒
Shopping
⚙️
Settings
+
+
+
+
+
Desktop · 1040px
+
+
+ +
Plan
📅Planner
📖Recipes
🛒Shopping
Account
👨‍👩‍👧Household
⚙️Settings
+
+
+
Recipe library
+
+ +
+
All (24)
+
Easy
+
Medium
+
Chicken
+
Fish
+
Veggie
+
+ +
+
🍝
Slow-roasted tomato pasta
45 min · Easy · Last cooked 3 days ago
VegetarianChild-friendly
+
🍗
Chicken stir-fry
25 min · Easy · 5 days ago
Chicken
+
🐟
Salmon teriyaki with rice
35 min · Medium · 2 weeks ago
Fish
+
🍄
Mushroom risotto
50 min · Medium · 2 weeks ago
Vegetarian
+
+
+
+
+
+
+
+

B1 · Recipe library

+
/* Desktop: 224px sidebar + topbar (search 220px + Add button) + content: filter chips row + 4-col grid.
+ * Desktop cards are richer: 100px image area + name (Fraunces 14px) + meta + tags row.
+ * Mobile: 2-col, 64px image, no tags on cards (too small).
+ * Filter chips: from tag table. Active: green-tint. 12px border-radius.
+ * Grid fills the content area directly — no wrapping card.
+ * Card click → B2 (recipe detail). Add button → B3 (empty form). */
+ + + + + + + + +
ElementValueNotes
Desktop
Grid4 columns, 12px gap, content padding 20px 24pxCards: radius-lg, border-default, overflow hidden
Card image100px height. hero_image_url → object-fit:cover. NULL → tint + emoji.Tint color based on first protein tag
Card content10px 12px padding. Name: Fraunces 14px. Meta: 10px muted. Tags: badge row.meta shows cook time + effort + "last cooked X ago"
Filter chips11px/500, 5px 14px pad, 12px radiusActive: green-tint bg + green-dark text. Others: border-default.
Mobile
Grid2 columns, 8px gapCards: 64px image, 12px name, 9px meta. No tags.
+
+
+ + + +
+

Add / edit recipe

B3
+
Single form for add + edit. Mobile: V1 single scroll. Desktop: V5 sidebar + topbar + split content (form left, tags + live preview panel right). The tags panel is a natural sidebar within the content area, not a floating card.
+
V1 mobile / V5 desktop — form left, tags + preview right on desktop
+ +
+
+
Mobile · 320px
+
+
9:45●●● WiFi 🔋
+
+
+
← Recipes
+
New recipe
+
Save
+
+
+
📷
Add photo
+
+
+
+
+
+
Ingredients
+
+
500g
Cherry tomatoes
×
+
300g
Penne pasta
×
+
3 cloves
Garlic
×
+
+ +
Tags (required)
+
Effort
+
EasyMediumHard
+
Category (pick ≥ 1)
+
ChickenFishVegetarianChild-friendlyPasta
+ +
+
+
+
+
+
Desktop · 1040px
+
+
+ +
Plan
📅Planner
📖Recipes
🛒Shopping
+
+
+
+
← Recipes/New recipe
+
+
+
+ +
+
📷 Add hero image
+
+
+
+
+
+
+
Ingredients
+
+
500g
Cherry tomatoes
×
+
300g
Penne pasta
×
+
3 cloves
Garlic
×
+
2 tbsp
Olive oil
×
+
+ +
Steps
+
1
Preheat oven to 180°C. Halve the tomatoes and place on a baking tray.
+
2
Drizzle with olive oil, season. Roast for 40 minutes.
+
3
Cook pasta. Toss with roasted tomatoes and garlic.
+ +
+ +
+
Tags (required)
+
Effort level
+
EasyMediumHard
+
Category
+
ChickenFishBeefVegetarianChild-friendlyPasta
+
+
Live preview
+
+
🍝
+
Slow-roasted tomato pasta
45 min · 4 servings · 4 ingredients
EasyVegetarianChild-friendly
+
+
+
+
+
+
+
+
+
+

B3 · Add/edit recipe

+
/* Desktop: 224px sidebar + topbar (breadcrumb + Save) + split content:
+ *   Left (flex:1, page bg): hero upload + name + serves/time/prep (3-col) + ingredients + steps
+ *   Right (280px, surface bg): effort chips + category chips + live preview card
+ * Form content is NOT in a card — it's directly on the page bg.
+ * Tags panel (right) uses surface bg as a section differentiator, not as a card.
+ * Mobile: single scroll, full width. Back + title + Save in topbar.
+ * Ingredient autocomplete: citext ILIKE from ingredient table. */
+ + + + + +
ElementValueNotes
Desktop
Form areaflex:1, page bg, 24px padding, border-rightContains: hero + name (16px input) + 3-col row + ingredients + steps
Tags panel280px, surface bg, 24px paddingEffort chips + category chips + divider + live preview card
Live previewMini B1 card inside the panelUpdates as user types. Shows name, time, servings, ingredient count, tags.
+
+
+ + +
+

Implementation Guide — J1 Add a Recipe

+ +

1. Journey Flow

+

B1 (Recipe library) → B3 (Add/edit form) → B1 (Recipe library). Actor: Planner only.

+ +

2. Screen B1 — Recipe Library

+
    +
  • Mobile: topbar + 2-col card grid (8px gap, 64px image, no tags on cards).
  • +
  • Desktop: 224px sidebar + topbar (search input 220px + Add button) + filter chips row + 4-col grid (12px gap, 100px image, tags visible as badge row).
  • +
  • Filter chips: sourced from the tag table. Active chip = green-tint bg / green-dark text. Inactive chip = border-default. Style: font-size:11px; font-weight:500; padding:5px 14px; border-radius:12px.
  • +
  • Card click → B2 (recipe detail). Add button → B3 (empty form).
  • +
+ +

3. Screen B3 — Add/Edit Recipe

+
    +
  • Single form component with two states: empty (new recipe) vs prefilled (edit existing recipe).
  • +
  • Design rule: B3 add = B3 edit — build once with two initial states.
  • +
  • Mobile: single scroll column, full width.
  • +
  • Desktop: 224px sidebar + topbar (breadcrumb + Save/Cancel buttons) + split content: form left (flex:1, page bg, 24px padding) + tags panel right (280px, surface bg).
  • +
+

Form sections:

+
    +
  1. Hero image upload (optional) — dashed border placeholder, click to upload.
  2. +
  3. Recipe name (required) — 16px font on desktop.
  4. +
  5. Serves / Cook time / Prep time — 3-col row on desktop, 2-col on mobile (prep time hidden or below).
  6. +
  7. Ingredients — editable list with autocomplete. Each row: quantity + name + remove button.
  8. +
  9. Steps — numbered list, optional at save. Each step: circle number + text.
  10. +
+

Tags (required):

+
    +
  • Effort level: Easy / Medium / Hard — single-select chip group.
  • +
  • Category: at least 1 required — Chicken, Fish, Beef, Vegetarian, Pasta, etc. Multi-select chips.
  • +
+

Desktop right panel: live preview card (mini B1 card) updates as user types — shows name, time, servings, ingredient count, and selected tags.

+

Ingredient autocomplete: citext ILIKE query against the ingredient table.

+ +

4. Data Operations

+ + + + + + + + + +
ScreenOperationTables
B1SELECT recipes with tagsrecipe JOIN recipe_tag + tag
B3INSERT / UPDATE reciperecipe
B3INSERT / DELETE ingredientsrecipe_ingredient
B3INSERT / DELETE stepsrecipe_step
B3INSERT / DELETE tagsrecipe_tag
+

Minimum to save: name + effort tag + at least 1 category tag.

+ +

5. Design Constraints

+
    +
  • Tags power the variety algorithm — they are not cosmetic. Ensure tags are always saved correctly.
  • +
  • If entered from a planner day slot, offer to assign the recipe to that day after save.
  • +
  • Steps are optional — recipes without steps can still be planned and cooked from the ingredient list only.
  • +
  • Form content is NOT in a card on desktop — it sits directly on the page background.
  • +
  • The tags panel uses surface bg as a section differentiator, not as a card wrapper.
  • +
+ +

6. Accessibility

+
    +
  • All form inputs must have associated <label> elements.
  • +
  • Ingredient and step lists must support keyboard navigation (add, remove, reorder).
  • +
  • Chip selections (effort level, category tags) must use proper ARIA attributes: role="radiogroup" for single-select effort, role="group" with aria-pressed for multi-select categories.
  • +
  • Live preview region should use aria-live="polite" to announce updates.
  • +
+
+ +
+ + diff --git a/specs/frontend/j2-plan-the-week.html b/specs/frontend/j2-plan-the-week.html new file mode 100644 index 0000000..734b7d3 --- /dev/null +++ b/specs/frontend/j2-plan-the-week.html @@ -0,0 +1,1085 @@ + + + + + + Recipe App — J2 Plan the Week · Journey Spec + + + + +
+ +
+
+

J2 — Plan the Week

+

Journey spec · Screens C1, C2, C3 · All breakpoints

+
+
+ Journey: J2
+ Screens: C1 · C2 · C3
+ Status: approved
+ Version: 1.0
+ Updated: 2026-04 +
+
+ + +
+
J2
+

Plan the week

Fill day slots, get variety-aware suggestions, review score. C1 is the app home screen.

C1 → C2 → C1 → C3 → C1 · Variety score always visible
+
+ + + + + + +
+

Weekly planner

C1
+
App home screen with all 3 breakpoints. Mobile: day strip + selected card + remaining list. Tablet: same stack, wider, 2-col remaining grid, inline nav pills. Desktop: 3-panel (sidebar 224px + 7-col calendar grid + detail panel 280px). Variety score always visible on all breakpoints.
+
V1 mobile · V2 tablet · V3 desktop — three fundamentally different layouts, not a scaled-up mobile
+ + +
+
Purpose & design rationale
+
+
+

What this screen does

+

The weekly planner is the app home screen. It lets the planner see all seven dinner slots for the current week at a glance, select any day to view the full meal, and access swap and cook actions without leaving the screen. For household members (read-only role) all edit and swap actions are hidden — the rest of the layout is identical.

+
+
+

The variety problem is always visible

+

The core pain point this app solves is meal repetition across the week. The variety score is therefore always on screen on all three breakpoints — it never hides in a tab, modal, or collapsed region. Ingredient repeat warnings appear inline at the tile level on desktop and in the detail panel across all breakpoints.

+
+
+
+ + +
+
Breakpoint 1 — Mobile · < 768px
+ +
+ +
+
9:41●●● WiFi 🔋
+
+
This week
+
+
+
+
+
+
+
8
+
+
Variety score
+
Good variety this week
+
Chicken in 2 meals
+
+
+
+
+ 31 Mar – 6 Apr +
+
+
+
Mo31
+
Tu1
+
We2
+
Th3
+
Fr4
+
Sa5
+
Su6
+
+
+
+
Wed · dinner2 Apr
+
+
Slow-roasted tomato pasta
+
+ 45 min + Easy + Child-friendly +
+
+
Cook now
+
Swap
+
+
+
+
Rest of the week
+
+
+
Thu
3
+
Chicken stir-fry
25 min · Easy
+
Swap
+
+
+
Fri
4
+
Chicken curry
40 min · Child-friendly
+
Swap
+
+
+
Sun
6
+
Lentil soup
45 min · Vegetarian
+
Swap
+
+
+
+
📅
Planner
+
📖
Recipes
+
🛒
Shopping
+
⚙️
Settings
+
+
+ +
+
+

Layout pattern

+

Five stacked fixed-height regions: top nav → variety banner → week strip → selected day card → scrollable remaining list. The tab bar is position: fixed at the bottom. Only the remaining days list scrolls.

+
+
+

Day strip

+

7-column grid, each chip 8px top+bottom padding. A 4px dot below the date is the only meal indicator: grey = no meal, green = meal planned, yellow-text = today, green-dark = selected. Today chip: yellow-tint bg + yellow-light border. Selected: green-tint + green-light. Tapping any chip updates the selected day panel immediately below.

+
+
+

Selected day card

+

Meal name in Fraunces 20px weight 400. Tags row (time, effort, attributes) then two equal-width action buttons. shadow-card elevation. When today is selected: 2px yellow border + yellow-tint background — the only 2px border in the system.

+
+
+

Variety banner

+

Always the first element below the nav. Never collapses. Score in Fraunces 28px weight 300. Warning row (yellow-text colour, yellow dot) appears when any ingredient appears in 2+ meals this week.

+
+
+

Remaining days list

+

Shows only days after the selected day. Date column: 36px wide. Meal name: Fraunces 14px. Meta: 11px muted DM Sans. Swap button: right-aligned 11px. Rows separated by 1px color-subtle dividers. Empty days are not shown — their absence is visible only via the dot in the strip.

+
+
+
+
+ + +
+
Breakpoint 2 — Tablet · 768px – 1024px
+
+

Relationship to mobile

+

The tablet uses the same five-region stack and the same interaction model as mobile. Key differences: the selected meal card expands to a two-column layout (info left, action buttons right); the remaining days list becomes a 2-column card grid; the variety banner gains a labelled progress bar; and the bottom navigation becomes an inline horizontal pill bar rather than a fixed screen overlay. A "Today" shortcut chip appears between the prev/next week buttons.

+
+
+
+
+
This week
+
+
+
+
8/10
+
+
Variety score
+
Good variety — no ingredient repeats more than twice
+
Chicken in 2 meals — consider swapping Friday
+
+
80%
+
+
+ 31 Mar – 6 Apr 2026 +
‹ PrevTodayNext ›
+
+
+
Mon31
+
Tue1
+
Wed2
+
Thu3
+
Fri4
+
Sat5
+
Sun6
+
+
+
+
Wednesday · dinner2 April 2026
+
+
+
Slow-roasted tomato pasta
+
+ 45 min + Easy + Child-friendly + Vegetarian +
+
Roasting the tomatoes concentrates their sweetness — great for the kids and easy to batch.
+
+
+ + + +
+
+
+
Rest of the week
+
+
Thu
3
Chicken stir-fry
25 min · Easy
+
Fri
4
Chicken curry
40 min · Child-friendly
+
Sat
5
No meal planned
+
+
Sun
6
Lentil soup
45 min · Vegetarian
+
+
+
📅 Planner
+
📖 Recipes
+
🛒 Shopping
+
⚙️ Settings
+
+
+
+
+

Selected meal card

Two-column layout: meal info (name 22px, tags, description) on the left, three stacked full-width action buttons on the right (min-width 120px). Description line is tablet and desktop only.

+

Remaining days grid

2-column CSS grid with 8px gap. Each card: date column (30px) + 1px vertical divider + meal name + meta + right arrow. Empty slots: dashed border, transparent bg, + icon right-aligned.

+

Navigation

Bottom nav becomes inline (not fixed), rendered as horizontal labelled pill items. Active item: green-tint bg + green-dark text. A "Today" shortcut chip sits between the prev/next week buttons.

+
+
+ + +
+
Breakpoint 3 — Desktop · > 1024px
+
+

Layout model change — not a scaled-up mobile

+

Desktop is a fundamentally different layout. The screen switches from a vertical single-column stack to a three-panel horizontal model: left sidebar (224px, fixed height, sticky), main calendar area (flex 1, only panel that scrolls), and right detail panel (280px, fixed). The day strip is replaced entirely by a 7-column calendar grid. The bottom tab bar is replaced by a persistent left sidebar nav. This is a deliberate layout change — not responsive scaling.

+
+
+
+
+ + +
+
Variety score
+
8/10
+
+
Good variety. No ingredient repeats more than twice.
+
Chicken on Thu + Fri — consider swapping
+ +
+
+
+
+
+
Weekly planner
+
31 Mar – 6 Apr 2026
+
+
+
+
+
+
+
Monday
31
Dinner
Pasta al forno
30 min
Easy · Child-friendly
+
Tuesday
1
Today · dinner
Grilled salmon
25 min
Easy
+
Wednesday
2
Dinner · selected
Slow-roasted tomato pasta
Easy
45 min · Vegetarian
+
Thursday
3
Dinner
Chicken stir-fry
⚠ Chicken
25 min
+
Friday
4
Dinner
Chicken curry
⚠ Chicken
40 min
+
Saturday
5
+
Add meal
+
Sunday
6
Dinner
Lentil soup
Vegetarian
45 min
+
+
+
+
Wednesday
2 April 2026 · dinner
+
+
Slow-roasted tomato pasta
+
+ 45 min + Easy + Vegetarian + Child-friendly +
+
+ + + +
+
+
+
Ingredients · serves 4
+
Cherry tomatoes500 g
+
Rigatoni320 g
+
Garlic cloves4, sliced
+
Olive oil ↻ Mon+Wed4 tbsp
+
Fresh basil1 handful
+
+
+
+
+
+
+
+

Three-panel structure

Sidebar 224px fixed + calendar flex 1 scrollable + detail panel 280px fixed. Sidebar and detail panel never scroll. Only the calendar area scrolls vertically. All three are 100% viewport height.

+

Calendar tiles

Each tile uses flex: 1 to fill its column. Column header has a 2px bottom border — yellow for today, green for selected. Tiles with repeated ingredients show a badge-warn chip (rgba(242,193,46,.25) bg). Empty slots: dashed border, centred + icon.

+

Variety — always visible

Bottom of the sidebar. Never scrolls out of view. Includes score, bar, message, ingredient-specific warning, and a "Review variety" button linking to screen C3.

+
+
+ + +
+

Machine-readable spec — C1 Weekly Planner

+

All values are real production sizes. Previews above are scaled for visual presentation only — never measure from them. Use tokens from color-palette-spec v1.0, typography-spec v1.0, and spacing-shape-spec v1.0.

+ +
/* C1 Implementation rules
+ * 1.  Default route on first load. App home screen.
+ * 2.  Variety score ALWAYS VISIBLE on all breakpoints. Never hidden or in a tab/modal.
+ * 3.  Today chip:    background yellow-tint (#FDF6D8), border 1px yellow-light (#F9E08A).
+ * 4.  Selected chip: background green-tint  (#E8F5EA), border 1px green-light  (#AEDCB0).
+ * 5.  Today meal card (mobile/tablet): 2px solid yellow (#F2C12E) border + yellow-tint bg.
+ *     Today tile (desktop): same 2px yellow border. This is the ONLY 2px border in the system.
+ * 6.  Meal names: always --font-display (Fraunces). All UI chrome: --font-sans (DM Sans).
+ * 7.  Chip dot: --color-border = no meal. --green = meal. --yellow-text = today. --green-dark = selected.
+ * 8.  Desktop: sidebar position sticky, height 100vh. Detail panel also sticky. Only cal-area scrolls.
+ * 9.  Ingredient repeat warnings: badge-warn (rgba(242,193,46,.25) bg + --yellow-text color) on tiles.
+ *     In detail panel: repeat rows use --yellow-text for name AND quantity text.
+ * 10. Household member role: hide swap buttons, hide "+ Add meal" button. Show read-only badge.
+ * 11. Empty day slot mobile: not shown in the remaining days list (only shown via dot in strip).
+ *     Empty day slot tablet/desktop: dashed 1px --color-border, transparent bg, centred + (18px --color-border).
+ * 12. Meal description text (13px DM Sans muted, line-height 1.5): tablet + desktop only. Hidden on mobile.
+ */
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Region / elementReal production valueNotesBreakpoints
Layout & breakpoints
Mobile breakpoint< 768pxSingle-column vertical stack, fixed bottom tab bar, body full-widthmobile
Tablet breakpoint768px – 1024pxSame stack structure, wider panels, inline bottom nav. No fixed tab bar.tablet
Desktop breakpoint> 1024px3-panel horizontal: sidebar + calendar + detail paneldesktop
Desktop sidebar width224px fixedposition: sticky; height: 100vh. Contains logo, nav, variety score.desktop
Desktop detail panel width280px fixedposition: sticky; height: 100vh. Hidden on mobile and tablet.desktop
Desktop calendar gapgap: 8px between columns (--space-2)grid-template-columns: repeat(7, 1fr)desktop
Desktop calendar padding20px all sides (--space-5)Inside the scrollable cal-area divdesktop
Mobile page gutter16px each side (--space-4)Applied to all content regions individually, not a wrappermobile
Tablet page gutter20px–24px each side (--space-5 / --space-6)Variety banner and selected card: 20px. Week header and strip: 20px.tablet
Tablet remaining grid gap8px (--space-2)2-column CSS gridtablet
Navigation
Mobile top nav padding10px 16px (--space-2 --space-4)position: sticky; top: 0; z-index: 10; border-bottom: --border-defaultmobile
Mobile top nav titleFraunces 20px weight 500, letter-spacing -0.02em"This week" — updates to week range on scroll if implementedmobile
Tablet top nav padding14px 20px (--space-3 --space-5)Title: Fraunces 24px weight 500. Right side adds "+ Add meal" button.tablet
Desktop topbar padding10px 24px (--space-2 --space-6)Title: Fraunces 20px weight 500. Week nav inline left. Today + Add meal right.desktop
Desktop sidebar nav itempadding: 7px 6px; font-size: 13px; border-radius: --radius-md (6px)Active: green-tint bg + green-dark text + weight 500. Icon 16px, 20px wide.desktop
Mobile tab barposition: fixed; bottom: 0; padding-bottom: 20px (safe area)4 items. Active icon: green-tint bg. Active label: green-dark color. Label: 10px DM Sans weight 500.mobile
Tablet nav barposition: static; inline at bottom; padding: 10px 20px 14pxHorizontal labelled pills. Active: green-tint bg + green-dark text.tablet
Nav prev/next buttonsDM Sans 11–12px, padding: 4–5px 8–10px, radius-sm (4px), color-subtle bg, border-defaultMobile: icon-only (⟨ ⟩) 32x32px. Tablet/desktop: text "‹ Prev" / "Next ›".all
"Today" shortcut chipDM Sans 10–11px weight 500, color-subtle bg, border-default, radius-smBetween prev/next buttons. Tablet and desktop only.tablet, desktop
"+ Add meal" buttonDM Sans 12–13px weight 500, green bg (#3D8C4A), white text, radius-md (6px), padding 7–8px 14–18pxPlanner role only. Hidden for household members.tablet, desktop
Variety score
Component backgroundyellow-tint (#FDF6D8) bg, 1px yellow-light (#F9E08A) border, radius-lg (10px)Identical on all breakpointsall
Mobile positionmargin: 16px 16px 0 (top + sides). First content after nav.padding: 8px 16px (--space-2 --space-4). Never collapses.mobile
Tablet positionmargin: 14px 20px 0. padding: 12px 16px.Same structure, slightly largertablet
Desktop positionBottom of sidebar. margin: 0 8px 14px. padding: 10px 12px.Always visible. Never scrolled by any panel.desktop
Score numberFraunces 28px mobile / 28px tablet / 40px desktop, weight 300, letter-spacing -0.02em, line-height 1Followed inline by denominator "/10" in DM Sans 12–16px mutedall
Eyebrow labelDM Sans 8–10px, weight 500, letter-spacing 0.08–0.1em, uppercase, --yellow-text (#8A6800)Always first text inside the componentall
Status messageDM Sans 9–11px, --color-text-mutedE.g. "Good variety this week"all
Warning rowDM Sans 9–11px, --yellow-text, flex row, 4–5px yellow dot (border-radius 50%)Only shown when any ingredient appears in 2 or more mealsall
Progress barheight: 3–5px, track: yellow-light, fill: yellow, radius: 99pxWidth = variety score as percentage (score 8 = 80%)all
"Review variety" buttonDM Sans 10px weight 500, color-page bg, yellow-light border, yellow-text color, radius-sm, padding 5pxDesktop sidebar only. Links to screen C3 (variety review).desktop
Day strip (mobile + tablet)
Strip gridgrid-template-columns: repeat(7, 1fr); gap: 2–3px mobile / 5–6px tabletpadding: 0 16px 8–12pxmobile, tablet
Chip padding5–8px top+bottom / 1–4px left+rightborder-radius: --radius-md (6px) mobile / --radius-lg (10px) tabletmobile, tablet
Chip abbreviationDM Sans 7–9px, weight 500, tracking 0.05–0.06em, uppercase, --color-text-muted2 letters on mobile (Mo Tu), 3 letters on tablet (Mon Tue)mobile, tablet
Chip date numberDM Sans 11–14px, weight 500, --color-text, line-height 1–1.1mobile, tablet
Chip dot3–4px diameter circle, border-radius: 50%No meal: --color-border. Has meal: --green (#3D8C4A). Today: --yellow-text (#8A6800). Selected: --green-dark (#2E6E39).mobile, tablet
Today chipbackground: --yellow-tint (#FDF6D8); border: 1px solid --yellow-light (#F9E08A)Abbreviation colour: --yellow-text. Dot colour: --yellow-text.mobile, tablet
Selected chipbackground: --green-tint (#E8F5EA); border: 1px solid --green-light (#AEDCB0)Abbreviation colour: --green-dark. Dot colour: --green-dark.mobile, tablet
Calendar grid (desktop only)
Column header day nameDM Sans 9–10px, weight 500, tracking 0.08em, uppercase, --color-text-mutedmargin-bottom: 3pxdesktop
Column header date badge24x24px, border-radius: 4px (--radius-sm), DM Sans 12–14px weight 500, --color-textToday col: yellow (#F2C12E) bg. Selected col: green-tint bg + green-dark text. Default: no bg.desktop
Column header bottom border2px solidDefault: --color-border. Today column: --yellow (#F2C12E). Selected column: --green (#3D8C4A).desktop
Tile padding8px 8px 10px (top / sides / bottom)border-radius: --radius-lg (10px). flex: 1 to fill column height.desktop
Tile eyebrowDM Sans 8–9px, weight 500, tracking 0.06–0.08em, uppercaseDefault: --color-text-muted. Today tile: --yellow-text. Selected tile: --green-dark.desktop
Tile meal nameFraunces 11–13px, weight 400, letter-spacing -0.01em, line-height 1.3No text truncation — tile height grows to fitdesktop
Tile at restbackground: --color-surface; border: 1px --color-border; box-shadow: --shadow-cardHover: border-color --green-light; box-shadow: --shadow-raiseddesktop
Today tileborder: 2px solid --yellow (#F2C12E); background: --yellow-tint (#FDF6D8)ONLY 2px border in the systemdesktop
Selected tileborder: 2px solid --green (#3D8C4A); background: --green-tint (#E8F5EA)Also 2px — matches today tile treatmentdesktop
Ingredient repeat badgebackground: rgba(242,193,46,0.25); color: --yellow-text (#8A6800); DM Sans 10px weight 500; padding: 2px 6px; border-radius: 3pxReplaces or supplements normal tags. Shows "⚠ [ingredient]".desktop
Empty day tileborder: 1px dashed --color-border; background: transparent; box-shadow: none; min-height: 60pxCentred content: + icon (16–18px --color-border) + "Add meal" label (9–10px --color-border)desktop
Selected day / detail panel
Mobile: selected area padding16px all sides (--space-4)Section above rule: eyebrow label left, date rightmobile
Mobile: meal card padding10–16px all sidesbackground: --color-surface; border: 1px --color-border; radius: --radius-lg (10px); box-shadow: --shadow-cardmobile
Meal name — mobileFraunces 20px, weight 400, letter-spacing -0.02em, line-height 1.25, margin-bottom: 8px--color-textmobile
Meal name — tabletFraunces 22px, weight 400, same other values--color-texttablet
Meal name — desktop detail panelFraunces 17px, weight 400, line-height 1.3, margin-bottom: 6pxSmaller because panel is narrower (280px)desktop
Meal descriptionDM Sans 13px, --color-text-muted, line-height 1.5Tablet + desktop only. Hidden on mobile.tablet, desktop
Actions — mobile2 buttons, flex row, equal width, DM Sans 12px weight 500, padding: 8px 12px, radius-md"Cook now" (green primary) + "Swap meal" (ghost)mobile
Actions — tablet3 buttons, stacked column in right half of card (min-width 120px), DM Sans 12px, padding: 7px 12px"Cook now" (primary) + "View recipe" (outline) + "Swap meal" (ghost)tablet
Actions — desktop3 buttons, stacked column, full panel width (280px minus padding), DM Sans 11px, padding: 6px"View recipe" (primary) + "Cook mode" (outline) + "Swap meal" (ghost)desktop
Desktop ingredient rowspadding: 4px 0 per row; border-bottom: 1px --color-subtle; DM Sans 11px name + 10px muted qtyRepeat ingredient rows: both name and qty use --yellow-text (#8A6800)desktop
Remaining days list / grid
Mobile list item padding6–12px top + bottom (--space-2 / --space-3)Separated by 1px --color-subtle bottom border. No left/right border.mobile
Date column — mobile listwidth: 26–36px, flex-shrink: 0Abbreviation: 7–9px DM Sans uppercase muted. Number: Fraunces 13–17px weight 300.mobile
Row meal name — mobileFraunces 11–14px, weight 400, letter-spacing -0.01em, --color-textwhite-space: nowrap; overflow: hidden; text-overflow: ellipsismobile
Row metadata — mobileDM Sans 9–11px, --color-text-mutedFormat: "{time} · {attribute}" e.g. "25 min · Easy"mobile
Swap buttonDM Sans 9–11px, padding: 3–4px 6–8px, radius-sm (4px), border-default, color-surface bgRight-aligned. Planner role only — hidden for household members.mobile, tablet
Tablet gridgrid-template-columns: 1fr 1fr; gap: 8px (--space-2); padding: 0 20px 16pxEach card: radius-lg, shadow-card, flex row. Date col (30px) + 1px vertical divider + content + arrow.tablet
Empty slot — tablet gridborder: 1px dashed --color-border; background: transparent; box-shadow: noneRight side: + icon (16px --color-border). Left: date col + divider as normal.tablet
Empty slot — mobileNot shown in the remaining listAbsence is communicated via grey dot in the day strip only.mobile
+
+
+ + + + + + +
+

Meal suggestions

C2
+
Mobile: V1 ranked list with context banner + reasoning per suggestion. Desktop: V4 sidebar + topbar + split content (week context left panel, ranked suggestions right). The week context panel shows what's already planned and why certain recipes are filtered.
+
V1 ranked list (mobile) · V4 split context (desktop)
+ +
+
+
Mobile · 320px
+
+
9:41●●● WiFi 🔋
+
+
+
← Planner
+
Suggestions
+
+
+
+
+
Suggesting for Wednesday, 2 Apr
+
Avoiding: chicken (Mon), tomato (Tue). Balancing effort.
+
+
1
Salmon teriyaki with rice
35 min · Medium · Fish
✓ No fish this week · different protein
Pick →
+
2
Mushroom risotto
50 min · Medium · Vegetarian
✓ No veggie since last week
Pick →
+
3
Thai green curry
40 min · Medium · Chicken
⚠ Chicken again — 2 days apart
Pick →
+
4
Beef bourguignon
2h 30m · Hard · Beef
✓ Never cooked — try something new!
Pick →
+
Browse full library →
+
+
+
+
+
+
Desktop · 1040px
+
+
+ +
Plan
📅Planner
📖Recipes
🛒Shopping
+ +
+
Variety score
+
8/10
+
+
+
+
Suggestions for Wednesday, 2 Apr
← Back to planner
+
+ +
+
This week so far
+
+
Mon — Chicken stir-fry
Chicken · Easy · 25 min
+
+
+
Tue — Tomato pasta
Veggie · Easy · 45 min
+
+
+
Wed — ?
Picking now
+
+
+
Thu–Sun — empty
+
+
Filter reasons
+
+
• Avoiding chicken (Mon)
+
• Avoiding tomato-heavy (Tue)
+
• Preferring medium effort (2 easy in a row)
+
+
+ +
+
1
Salmon teriyaki with rice
35 min · Medium · Fish
✓ Fresh protein · effort balance
Pick →
+
2
Mushroom risotto
50 min · Medium · Vegetarian
✓ No veggie for 10 days
Pick →
+
3
Beef bourguignon
2h 30m · Hard · Beef
✓ Never cooked — try it!
Pick →
+
4
Thai green curry
40 min · Medium · Chicken
⚠ Chicken 2 days apart
Pick →
+
Browse full library instead →
+
+
+
+
+
+
+
+

C2 · Meal suggestions

+
/* Desktop: 224px sidebar (variety score at bottom) + topbar + split content:
+ *   Left panel (280px, surface bg): week-so-far mini cards + filter reason bullets
+ *   Right panel (flex:1, page bg): ranked suggestion cards with Pick action
+ * The context panel is a page section, not a floating card.
+ * Mobile: context banner (green-tint, collapsible) + ranked list below.
+ * Pick → writes week_plan_slot → returns to C1.
+ * "Browse full library" → B1 in selection mode. */
+ + + + + + +
ElementValueNotes
Desktop
Context panel280px, surface bg, border-rightWeek meals + current slot (yellow) + filter reasons
Suggestionsflex:1, page bg, 20px paddingSame sg-card component as mobile but wider
Mobile
Context bannergreen-tint, radius-lg, 10px 12px padDay label + filter summary. Collapsed on mobile.
+
+
+ + + + + + +
+

Variety review

C3
+
V1 Score breakdown. Desktop: sidebar + topbar + content with score hero area and sub-scores on the left, a 7-day protein distribution visual on the right, and warnings spanning the full width below.
+
V1 · Score breakdown — big score → sub-scores → protein grid → warnings
+ +
+
+
Mobile · 320px
+
+
9:41●●● WiFi 🔋
+
+
+
← Planner
+
Variety review
+
+
+
+
+
8
+
out of 10 · Good variety
+
+
+
Score breakdown
+
+
Protein diversity9/10
+
Ingredient overlap7/10
+
Effort balance8/10
+
+
Warnings
+
+
Chicken appears twice
+
Monday and Thursday — 3 days apart is acceptable but reduces your score.
+
+
+
+
+
+
+
Desktop · 1040px
+
+
+ +
Plan
📅Planner
📖Recipes
🛒Shopping
+
+
+
← Planner/Variety review
+
+ +
+ +
+
+
8
+
out of 10
Good variety this week
+
+
+
Score breakdown
+
+
Protein diversity9/10
+
Ingredient overlap7/10
+
Effort balance8/10
+
+
+ +
+
Protein spread
+
+
Mon
🍗
+
Tue
🥬
+
Wed
🐟
+
Thu
🍗
+
Fri
🥩
+
Sat
+
Sun
🍝
+
+
Effort balance
+
+
Easy ×3
+
Medium ×3
+
Hard ×1
+
+
+
+ +
Warnings
+
+
Chicken appears twice
+
Monday (stir-fry) and Thursday (curry) — 3 days apart is acceptable but reduces your score. Swap Thursday to improve to 9.
+
+
+
Garlic in 5 of 7 meals
+
Consider a garlic-free recipe for variety. This has minor impact on score.
+
+
+
+
+
+
+
+

C3 · Variety review

+
/* Desktop: sidebar + topbar (breadcrumb ← Planner / Variety review) + content:
+ *   Top area: 2-col flex. Left: big score (72px) + progress bar + sub-score rows. Right: 7-day protein grid + effort bar.
+ *   Bottom area: full-width warning cards.
+ * Content sits directly on page bg — no wrapper card.
+ * Mobile: stacked. Score → sub-scores → warnings. No protein grid (too small).
+ * Score is COMPUTED (variety CTE from data model), never stored. */
+ + + + + + +
ElementValueNotes
Desktop
Score areaflex:1. Score: Fraunces 72px/300. Bar: 200px wide, 6px, yellow.Sub-scores: bordered rows, not in a card.
Protein grid320px. 7-col grid, 6px gap. Cells: 44px height, colored by protein.Repeated protein: 2px yellow border on matched cells (Mon + Thu chicken).
Effort barProportional flex row. Green/yellow/red segments.Labels: "Easy ×3", "Medium ×3", "Hard ×1"
WarningsFull width, yellow-tint, radius-lgTitle 13px/500 + body 12px. Below the 2-col area.
+
+
+ + + + + + +
+

LLM Context — J2 Plan the Week

+ +

1. Journey Flow

+

C1 (planner) → C2 (suggestions) → C1 → C3 (variety review) → C1. The actor is the Planner only. Household members see C1 in read-only mode (all action buttons hidden). C1 is the app home screen and the default route.

+ +

2. Screen C1 — Weekly Planner (HOME SCREEN)

+
    +
  • Three fundamentally different layouts — NOT a scaled-up mobile. Each breakpoint has a distinct layout model.
  • +
  • Mobile (< 768px): day strip (7-col grid) + selected day card + remaining list + fixed bottom tabs. Five stacked regions, only the remaining list scrolls.
  • +
  • Tablet (768–1024px): same stack, wider. 2-col remaining grid. Inline nav pills (not fixed tab bar). Progress bar appears on the variety banner. "Today" shortcut chip between prev/next week buttons.
  • +
  • Desktop (> 1024px): 3-panel layout — sidebar 224px (position: sticky, 100vh) + calendar (flex:1, scrollable, 7-col grid) + detail panel 280px (position: sticky, 100vh). Only the calendar area scrolls.
  • +
  • VARIETY SCORE ALWAYS VISIBLE on all breakpoints — never hidden, tabbed, or collapsed. Mobile: banner below nav. Tablet: banner with progress bar. Desktop: bottom of sidebar.
  • +
  • Today: yellow treatment — 2px border (the ONLY 2px border in the system) + yellow-tint background.
  • +
  • Selected: green treatment — 2px border + green-tint background.
  • +
  • Ingredient repeat warnings: shown on tiles as badge-warn chips (desktop) and in the detail panel as yellow-text ingredient rows (all breakpoints).
  • +
  • Household members: all action buttons hidden (swap, add meal, cook now). Read-only view, layout otherwise identical.
  • +
+ +

3. Screen C2 — Meal Suggestions

+
    +
  • Suggestions are sorted by the VARIETY ALGORITHM (not effort): avoids ingredients from past 3 days, avoids same-protein on adjacent days, balances effort across the week.
  • +
  • Reasoning badges: green background (good match, e.g. "No fish this week") or yellow background (warning, e.g. "Chicken again — 2 days apart").
  • +
  • Mobile: context banner (green-tint, collapsible) at top showing day + filter summary, then ranked suggestion list below.
  • +
  • Desktop: context panel (280px, surface bg, border-right) showing week-so-far cards + filter reasons, plus suggestions panel (flex:1, page bg).
  • +
  • Pick action: writes week_plan_slot → returns to C1. "Browse full library" links to B1 in selection mode.
  • +
+ +

4. Screen C3 — Variety Review

+
    +
  • Score breakdown: protein diversity (x/10), ingredient overlap (x/10), effort balance (x/10).
  • +
  • Desktop layout: score + sub-scores on the left (flex:1) + 7-day protein grid (320px) + effort bar on the right. Warnings span full width below.
  • +
  • Protein grid: 7 columns, each cell 44px height, colored by protein type. Repeated proteins get a 2px yellow border on matched cells (e.g. Mon + Thu chicken).
  • +
  • Effort bar: proportional flex segments — easy = green-tint, medium = yellow-tint, hard = red (#FDEAEA). Labels like "Easy ×3".
  • +
  • Mobile: stacked vertically — score → sub-scores → warnings. No protein grid (too small for 320px viewport).
  • +
+ +

5. Critical Design Rules

+
    +
  • Variety score is the core value proposition — always visible on every screen, every breakpoint. Never hidden behind a tab, modal, or collapse.
  • +
  • Meal names: always Fraunces (--font-display). UI chrome: always DM Sans (--font-sans).
  • +
  • 2px borders ONLY on today/selected states. Everything else uses 1px borders.
  • +
  • Desktop: only the calendar area scrolls. Sidebar and detail panel are both position: sticky, height: 100vh.
  • +
  • J3 "mark as cooked" feeds variety history which filters J2 suggestions — this feedback loop is critical. Cooking history from J3 informs the variety algorithm that ranks suggestions in C2.
  • +
+ +

6. Data Operations

+
    +
  • The variety score is COMPUTED via a CTE (Common Table Expression) from the data model. It is never stored as a column — always derived at query time from the week's planned meals and cooking history.
  • +
  • C2 Pick action writes to the week_plan_slot table and returns to C1.
  • +
  • C3 reads the same computed variety CTE to break down the score into its three components.
  • +
+
+ +
+ + diff --git a/specs/frontend/j3-cook-tonight.html b/specs/frontend/j3-cook-tonight.html new file mode 100644 index 0000000..c2a18e8 --- /dev/null +++ b/specs/frontend/j3-cook-tonight.html @@ -0,0 +1,395 @@ + + + + + + J3 — Cook Tonight + + + + +
+ + +
+
J3
+

Cook tonight

Recipe detail → cook mode → mark as cooked. Kitchen context.

C1 → B2 → B4 → C1 · 16px body, 1.75 line-height, wake lock
+
+ + +
+

Recipe detail

B2
+
V2 Hero header. Desktop: sidebar + full-width hero banner spanning the content area + two-column content below (ingredients left, steps right). The hero fills the horizontal space — it's not a card, it's a page section with a distinct background.
+
V2 · Hero header — banner CTA, 2-col content on desktop
+ +
+
+
Mobile · 320px
+
+
18:32●●● WiFi 🔋
+
+
+
← Planner
+
Slow-roasted tomato pasta
+
+ 45 min + Easy + Serves 4 +
+ +
+
+
Ingredients
+
+
500g
Cherry tomatoes
+
300g
Penne pasta
+
3 cloves
Garlic
+
2 tbsp
Olive oil
+
+
Steps
+
1
Preheat oven to 180°C. Halve tomatoes.
+
2
Drizzle with oil, season, roast 40 min.
+
3
Cook pasta. Toss with roasted tomatoes and garlic.
+
+
+
+
+
+
Desktop · 1040px
+
+
+ +
Plan
📅Planner
📖Recipes
🛒Shopping
+
+
+
← Recipes/Slow-roasted tomato pasta
+ +
+
+
Slow-roasted tomato pasta
+
+ 45 min + Easy + Serves 4 + Vegetarian + Child-friendly +
+
Roasting the tomatoes concentrates their sweetness — great for the kids and easy to batch cook.
+
+ +
+ +
+
+
Ingredients · 4 items
+
500g
Cherry tomatoes
+
300g
Penne pasta
+
3 cloves
Garlic
+
2 tbsp
Olive oil
+
+
+
Steps · 3
+
1
Preheat oven to 180°C. Halve the cherry tomatoes and place cut-side up on a large baking tray.
+
2
Drizzle generously with olive oil, season with salt and pepper. Roast for 40 minutes until caramelized.
+
3
Cook pasta according to package. Toss with roasted tomatoes and minced garlic. Serve with fresh basil.
+
+
+
+
+
+
+
+

B2 · Recipe detail

+
/* Desktop: sidebar + topbar (breadcrumb + Edit button) + hero banner (full width, green-tint) + 2-col below.
+ * Hero: name Fraunces 28px + tag pills + description + Cook button on the right.
+ * Below hero: ingredients (left, border-right) + steps (right). Both panels scroll independently.
+ * Hero with image: hero_image_url as bg, 40% dark overlay, text in white.
+ * Mobile: hero banner → stacked ingredients → steps.
+ * "Start cooking" → B4. "Edit" → B3 in edit mode. */
+ + + + + + + +
ElementValueNotes
Desktop hero
LayoutFull content width, green-tint bg, 32px paddingFlex: info left (flex:1) + Cook button right (flex-shrink:0)
NameFraunces 28px/500, green-deeperWith image: #fff on dark overlay
Desktop content below hero
Ingredientsflex:1, 24px padding, border-rightir-row component. Scrolls independently.
Stepsflex:1, 24px paddingNumbered circles (28px) + 14px body text, 1.6 line-height.
+
+
+ + + +
+

Cook mode

B4
+
V1 Centered step. Full-screen on ALL breakpoints — intentionally no sidebar, no tabs, no nav chrome. Kitchen context doesn't change with screen size. Only the text max-width scales (260→400px). The entire screen body is the tap target.
+
V1 · Centered step — same layout everywhere. No desktop sidebar. Tap anywhere.
+ +
+
+
Mobile · Step 2 of 3
+
+
18:45●●● WiFi 🔋
+
+
+
✕ Exit
+
Step 2 of 3
+
+
+
+
+
2
+
Drizzle with olive oil, season generously with salt and pepper. Roast for 40 minutes until caramelized.
+
+
Tap anywhere for next step →
+
+
+
+
+
Desktop · SAME layout, wider text
+
+
+
✕ Exit
+
Step 2 of 3
+
+
+
+
+
2
+
Drizzle with olive oil, season generously with salt and pepper. Roast for 40 minutes until caramelized.
+
+
Tap anywhere for next step →
+
+
+
+
+

B4 · Cook mode · KITCHEN CRITICAL

+
/* FULL SCREEN on all breakpoints. NO sidebar. NO tabs. NO nav chrome.
+ * Body text: EXACTLY 16px, line-height 1.75. NON-NEGOTIABLE.
+ * Max text width: 260px mobile, 320px tablet, 400px desktop.
+ * Step number: Fraunces 56px mobile, 72px desktop. Green-light.
+ * TAP ANYWHERE to advance. Wake lock on enter. Exit = top-left error red.
+ * Final step: "Done — mark as cooked" → cooking_log INSERT → C1.
+ * This is an EXCEPTION to nav-spec: no sidebar, no breadcrumbs, no tabs. */
+ + + + + + + +
ElementValueNotes
Layout — IDENTICAL all breakpoints
Body text16px, line-height 1.75NON-NEGOTIABLE
Max text width260px mobile / 320px tablet / 400px desktopOnly difference between breakpoints
Step numberFraunces 56px mobile / 72px desktop, weight 300, green-lightVisible from arm's length
Tap targetEntire body areaonclick → next step
Wake locknavigator.wakeLock.request('screen')On enter, release on exit/done
+
+
+ + + +
+

LLM Implementation Instructions — J3 Cook Tonight

+

This section provides structured guidance for code-generating LLMs implementing the J3 journey. Follow these rules exactly.

+ +

1. Journey Flow

+

C1 (today highlight) → B2 (recipe detail) → B4 (cook mode) → C1

+
    +
  • Actor: Planner
  • +
  • Context: Mobile, hands busy, kitchen environment
  • +
  • The user taps today's meal on the planner (C1), views the recipe (B2), enters cook mode (B4), steps through instructions, marks as cooked, and returns to the planner (C1).
  • +
+ +

2. Screen B2 — Recipe Detail

+

Mobile layout

+
    +
  • Green-tint hero banner at top: back link ("← Planner"), title in Fraunces 24px, pill tags (time, difficulty, servings), and a full-width "Start cooking" button.
  • +
  • Below the hero: stacked ingredients section, then steps section.
  • +
+

Desktop layout

+
    +
  • Sidebar (224px) + topbar with breadcrumb ("← Recipes / Recipe Name") and Edit button.
  • +
  • Full-width hero banner: green-tint background, 32px padding. Flex layout with recipe info left (flex:1) and Cook button right (flex-shrink:0).
  • +
  • Below hero: 2-column layout. Ingredients left (flex:1, border-right) + steps right (flex:1). Both panels scroll independently.
  • +
+

Hero variants

+
    +
  • With image: hero_image_url as background, 40% dark overlay, all text rendered in white.
  • +
  • Without image: green-tint background, dark text (green-deeper for title).
  • +
+

Component details

+
    +
  • Ingredients: Read-only .ir rows (quantity + name). Quantities are scaled to the saved serving count for the planned meal.
  • +
  • Steps: Numbered circles (28px diameter on desktop, 22px mobile) + step text (14px, line-height 1.6 on desktop; 13px, line-height 1.5 on mobile).
  • +
+

Navigation

+
    +
  • "Start cooking" button → navigates to B4 (cook mode).
  • +
  • "Edit" button → navigates to B3 (recipe form, prefilled with current recipe data).
  • +
+ +

3. Screen B4 — Cook Mode (KITCHEN CRITICAL)

+

This screen is the single exception to all responsive and navigation patterns in the app.

+

Layout rules

+
    +
  • IDENTICAL LAYOUT on ALL breakpoints — this is the ONLY screen that ignores responsive patterns.
  • +
  • NO sidebar, NO tabs, NO navigation chrome on ANY breakpoint. This is an explicit exception to the nav-spec.
  • +
+

Topbar

+
    +
  • Three-column flex: Exit button (left, error red var(--color-error)) + progress indicator (center, "Step N of M") + empty spacer (right).
  • +
+

Progress bar

+
    +
  • Height: 4px. Track: var(--color-subtle). Fill: var(--green). Border-radius: 2px.
  • +
  • Width percentage: (currentStep / totalSteps) * 100%.
  • +
+

Body

+
    +
  • Centered step number: Fraunces, weight 300, var(--green-light). Size: 56px (mobile) / 72px (desktop).
  • +
  • Step text: EXACTLY 16px, line-height 1.75 — NON-NEGOTIABLE. This is a readability requirement for kitchen use with dirty hands.
  • +
  • Max text width: 260px (mobile) / 320px (tablet) / 400px (desktop).
  • +
+

Interaction

+
    +
  • TAP ANYWHERE to advance: The entire body area is the tap target. No fine motor precision required.
  • +
  • On the final step, the tap target label changes to "Done — mark as cooked".
  • +
  • Tapping on the final step triggers: cooking_log INSERT with recipe_id and cooked_date set to today's date, then navigates back to C1.
  • +
+

Wake lock

+
    +
  • On entering B4: call navigator.wakeLock.request('screen') to prevent the screen from sleeping.
  • +
  • On exiting B4 (via Exit button or "Done"): release the wake lock.
  • +
+ +

4. Critical Feedback Loop

+

The cooking_log table is the data source for the variety/repetition algorithm used in J2 (meal suggestions). Meals cooked more recently are weighted more heavily in the repetition filter, causing the algorithm to deprioritize them in future suggestions. This means J3's "mark as cooked" action directly makes J2's suggestions smarter over time.

+ +

5. Data Operations

+ + + + + + +
ScreenOperationTables
B2READrecipe, recipe_ingredient, ingredient, recipe_step
B4WRITEcooking_log INSERT (recipe_id, cooked_date)
+ +

6. Accessibility

+
    +
  • B4's tap target is the entire screen body — accessible with one finger, no fine motor precision needed. This is intentional for kitchen use where hands may be wet or dirty.
  • +
  • The wake lock prevents the screen from sleeping mid-recipe, eliminating the need to unlock the device with messy hands.
  • +
  • Step text at 16px with 1.75 line-height ensures readability at arm's length.
  • +
+
+ +
+ + diff --git a/specs/frontend/j4-adapt-on-the-fly.html b/specs/frontend/j4-adapt-on-the-fly.html new file mode 100644 index 0000000..e0f3585 --- /dev/null +++ b/specs/frontend/j4-adapt-on-the-fly.html @@ -0,0 +1,295 @@ + + + + + + J4 — Adapt on the Fly + + + + +
+ + +
+
J4
+

Adapt on the fly

Mid-week swap in ≤ 3 taps. Action sheet → pick replacement → done.

C1 → action sheet → C2 swap → C1 · Easiest first
+
+ + +
+

Swap trigger

C1 overlay
+
Mobile: tap meal → bottom action sheet (Swap / Cook / View / Cancel). Desktop: no action sheet needed — the C1 detail panel already has a "Swap meal" button. Clicking it transitions the detail panel content to show swap suggestions inline.
+
V4 · Action sheet (mobile) · Detail panel button (desktop)
+ +
+
+
Mobile · Action sheet
+
+
17:15●●● WiFi 🔋
+
+
This week
+
+
Mon · Chicken stir-fry
+
Tue · Tomato pasta
+
+
+
+
+
Tuesday — Tomato pasta
+
45 min · Easy · Vegetarian
+
+
↻ Swap this meal
+
🍳 Cook now
+
👁 View recipe
+
Cancel
+
+
+
+
+
+
+
+
+

Swap trigger

+
/* Mobile: tap meal card → bottom action sheet. Planner dims to 40%.
+ * Sheet: drag handle + meal name + meta + 4 action buttons stacked.
+ * Swap = orange-tint. Cook = green-tint. View = subtle. Cancel = no bg.
+ * Desktop: no action sheet. C1 detail panel has "Swap meal" ghost button (per planner-spec).
+ * Clicking "Swap meal" transitions the detail panel to show swap suggestions inline.
+ * Tap count: Mobile 3 (card → Swap → Pick). Desktop 2 (Swap → Pick). */
+
+
+ + + +
+

C2 in swap context

C2 swap
+
Mobile: bottom sheet over C1 with "Replacing" banner + easiest-first suggestions. Desktop: swap suggestions render inline in the C1 detail panel (replacing the meal detail) — the calendar grid stays visible alongside. No page navigation needed.
+
V1 · Quick swap sheet (mobile) · Inline detail panel (desktop)
+ +
+
+
Mobile · Swap sheet
+
+
17:16●●● WiFi 🔋
+
+
This week
+
+
+
+
+
Replacing Tuesday's meal
+
Tomato pasta · 45 min · Easy
+
+
Swap to (easiest first)
+
+
Quick carbonara
20 min · Easy · Pasta
+
Pick
+
+
+
Chicken stir-fry
25 min · Easy
⚠ Already on Mon
+
Pick
+
+
+
Mushroom risotto
50 min · Medium · Veggie
+
Pick
+
+
Cancel
+
+
+
+
+
+
+
+

C2 swap context

+
/* Mobile: bottom sheet over dimmed C1. "Replacing" banner + suggestion list.
+ * Sorted EASIEST FIRST (effort ASC, cook_time ASC) — different from J2.
+ * "Pick" → UPDATE week_plan_slot. Dismiss sheet. No confirmation dialog (undo toast instead).
+ * Desktop: detail panel (280px) transitions in-place. Calendar grid stays visible.
+ * Replacing header: orange-tint, old meal struck through.
+ * Suggestion cards: compact, fitting panel width. Name + meta + "Pick" link.
+ * Tap count: Mobile 3. Desktop 2 (faster — no action sheet intermediary). */
+
+
+ + + +
+

LLM Implementation Instructions — J4 Adapt on the Fly

+ +

1. Journey Flow

+

C1 → action sheet (mobile) or detail panel button (desktop) → swap suggestions → pick → C1. + Actor: Planner. Frequency: 1-2x/week. Urgency: HIGH.

+ +

2. Constraint: 3 taps maximum

+

From "Swap" to updated plan in no more than 3 taps.

+
    +
  • Mobile: 3 taps — card → Swap → Pick
  • +
  • Desktop: 2 taps — Swap → Pick (no action sheet intermediary)
  • +
+ +

3. Mobile: Action Sheet

+
    +
  • Bottom sheet pulls up on meal tap; background dims to 40% opacity.
  • +
  • Drag handle: 32px wide, 4px height, var(--color-border) background.
  • +
  • Meal title in 15px display font + metadata in 11px muted text.
  • +
  • 4 stacked buttons: +
      +
    1. "Swap this meal"orange-tint bg / orange-dark text
    2. +
    3. "Cook now"green-tint bg / green-dark text
    4. +
    5. "View recipe"subtle bg / muted text
    6. +
    7. "Cancel" — no background, muted text
    8. +
    +
  • +
+ +

4. Mobile: Swap Suggestions (Bottom Sheet)

+
    +
  • "Replacing" banner: orange-tint background, old meal name struck through.
  • +
  • "Swap to (easiest first)" eyebrow label above suggestion list.
  • +
  • Compact suggestion cards: recipe name + time/effort/tag + "Pick" link on the right.
  • +
  • Sorted EASIEST FIRSTeffort ASC, cook_time ASC. This is DIFFERENT from C2 in J2, which sorts by variety score.
  • +
  • "Pick" action: UPDATE week_plan_slot with new recipe_id → dismiss sheet → show undo toast (NOT a confirmation dialog).
  • +
+ +

5. Desktop: Inline Panel

+
    +
  • No action sheet needed — the C1 detail panel (280px wide) already has a "Swap meal" ghost button.
  • +
  • Clicking the button transitions the detail panel content in-place to show swap suggestions.
  • +
  • Calendar grid stays visible alongside the panel at all times.
  • +
  • Same sorting (effort ASC, cook_time ASC) and "Replacing" header as mobile.
  • +
+ +

6. Why Easiest First

+

Mid-week swaps typically happen because the original plan was too ambitious. Sorting by effort makes the fastest, lowest-effort options most visible, matching the user's intent to simplify.

+ +

7. Data Operations

+
    +
  • Writes: week_plan_slot UPDATE — sets new recipe_id on the slot.
  • +
  • Swap is logged: both the original meal (marked as not cooked) and the replacement are recorded.
  • +
  • Original uncooked meal remains in the recipe library for future weeks.
  • +
  • Variety score recalculates immediately after swap.
  • +
+ +

8. Design Constraints

+
    +
  • Speed over deliberation — undo toast instead of confirmation dialog. The user is in a hurry mid-week.
  • +
  • Orange accent color for swap context: orange-tint background, orange-dark text on banners and primary action.
  • +
  • Variety filter still applies to suggestions (duplicates get a warning), just sorted differently than J2.
  • +
+
+ +
+ + diff --git a/specs/frontend/j5-shopping-list.html b/specs/frontend/j5-shopping-list.html new file mode 100644 index 0000000..fb6213f --- /dev/null +++ b/specs/frontend/j5-shopping-list.html @@ -0,0 +1,389 @@ + + + + + + Recipe App — J5 Shopping List Journey Spec + + + + + +
+ + +
+
+

J5 — Shopping list

+

Journey spec — Generate shopping list, real-time shared checklist

+
+
+ v1.0
+ Journey +
+
+ + +
+
J5
+

Generate shopping list

Merge ingredients, filter staples. Always live and shared with household.

C1 → D1 (always live) · Planner generates · All members add/remove/check off
+
+ + +
+

Shopping list (live)

D1
+
V1 Checklist with sources. Desktop: sidebar + topbar + two-column content — checklist on the left, a "This week's recipes" reference panel on the right that shows which recipes contributed which items. The panel is a page section (surface bg), not a card.
+
V1 · Checklist with sources — desktop: list left, recipe reference right
+ +
+
+
Mobile · 320px
+
+
10:24●●● WiFi 🔋
+
+
Shopping list
⚙️
+
+
+
+
Shared with household · 2 members online
+
+
5 items remaining
+
+
Cherry tomatoes
For: Tomato pasta
500g
+
Penne pasta
For: Tomato pasta
300g
+
Salmon fillet
For: Salmon teriyaki
400g
+
Jasmine rice
For: Teriyaki, Curry
500g
+
Soy sauce
For: Teriyaki, Stir-fry
4 tbsp
+
Coconut milk
For: Thai curry
400ml
+
Curry paste
For: Thai curry
2 tbsp
+
+
+ Add custom item
+
+
📅
Planner
📖
Recipes
🛒
Shopping
⚙️
Settings
+
+
+
+
+
Desktop · 1040px
+
+
+ +
Plan
📅Planner
📖Recipes
🛒Shopping
+
+
+
Shopping list
2 members online
+
+ +
+
5 items remaining · 2 checked off
+
Cherry tomatoes
For: Tomato pasta
500g
+
Penne pasta
For: Tomato pasta
300g
+
Salmon fillet
For: Salmon teriyaki
400g
+
Jasmine rice
For: Salmon teriyaki, Thai curry
500g
+
Soy sauce
For: Salmon teriyaki, Stir-fry
4 tbsp
+
+
Checked off
+
Coconut milk
For: Thai curry
400ml
+
Curry paste
For: Thai curry
2 tbsp
+
+
+ Add custom item
+
+ +
+
This week's recipes
+
+
Tomato pasta
+
Tue · 2 ingredients on list
+
+
+
Salmon teriyaki
+
Wed · 3 ingredients on list
+
+
+
Thai green curry
+
Thu · 2 ingredients on list
+
+
+
Chicken stir-fry
+
Mon · shared soy sauce
+
+
+
Filtered staples
+
Olive oil · Garlic · Salt · Pepper · Rice · Pasta
+
Edit staples →
+
+
+
+
+
+
+
+
+

D1 · Shopping list

+
/* Desktop: 224px sidebar + topbar (title + shared status badge) + 2-col content:
+ *   Left (flex:1, page bg): remaining count + checklist rows + "checked off" section + add custom
+ *   Right (280px, surface bg): recipe reference cards + filtered staples list + edit staples link
+ * Recipe reference panel: page-section with surface bg, not a floating card.
+ * Mobile: full-width checklist + shared banner + bottom tabs.
+ * Real-time sync: is_checked updates broadcast to all connected clients.
+ * Both roles: planner + member can view and check off. Only planner can regenerate. */
+ + + + + + + +
ElementValueNotes
Desktop
Checklist areaflex:1, page bg, 20px 24px paddingRemaining items + divider + checked items
Recipe reference280px, surface bg, border-leftRecipe name + day + ingredient count. Filtered staples below.
Shared state
Banner (mobile)blue-tint, blue dot, radius-lg"Shared · N online"
Badge (desktop)blue-tint pill in topbarCompact: dot + "N members online"
+
+
+ + + +
+

LLM instructions — J5 Shopping list journey

+

Authoritative implementation reference for the shopping list journey. Covers screen D1 and references A3/D3 (staples). Use this when building or modifying the shopping list feature.

+ +

1. Journey flow

+
/* J5 flow
+ * C1 (week confirmed) → D1 (shopping list, always live).
+ * Actor: Planner generates the list. All household members shop (view, check off, add items).
+ * Preconditions: J1 (recipes exist) + J2 (week is planned) for generating a list.
+ *                J6 (household setup) for shared access.
+ * There is NO draft/publish workflow — the list is always live. */
+ +

2. Screen D1 — Shopping list (live shared)

+
/* Mobile layout:
+ *   topbar (title + settings icon)
+ *   + blue-tint shared banner ("Shared with household · N members online", blue dot)
+ *   + checklist (unchecked items, then checked items below divider)
+ *   + "+ Add custom item" link (blue-dark, centred)
+ *   + bottom tabs (Planner | Recipes | Shopping [active] | Settings)
+ *
+ * Desktop layout:
+ *   sidebar (224px, dsb) + topbar (dtb: title + blue-tint "N members online" badge)
+ *   + split content area:
+ *     Left: checklist (flex:1, page bg, 20px 24px padding)
+ *       - eyebrow "N items remaining · N checked off"
+ *       - unchecked rows
+ *       - border-top divider → "Checked off" eyebrow (opacity .6) → checked rows
+ *       - "+ Add custom item" link (12px, blue-dark, font-weight 500)
+ *     Right: recipe reference panel (280px, surface bg, border-left, 20px padding)
+ *       - eyebrow "This week's recipes"
+ *       - recipe cards: page bg, border, radius-md, 10px padding
+ *         - recipe name (13px/500) + day + ingredient count (10px muted)
+ *       - border-top divider → "Filtered staples" eyebrow
+ *         - staple names inline (11px muted, dot-separated)
+ *         - "Edit staples →" link (11px, blue, font-weight 500) — links to D3
+ *
+ * Checklist row (.ck):
+ *   checkbox (.ck-b, 22px, radius 4px, 2px border)
+ *   + content (.ck-c): name (.ck-n, 14px) + source (.ck-s, 10px muted, "For: [recipe names]")
+ *   + quantity (.ck-q, mono 12px muted, flex-shrink 0)
+ *
+ * Checked state (.ck.d):
+ *   checkbox fills green with white checkmark
+ *   name gets line-through + muted colour
+ *   row moves below divider into "Checked off" section */
+ +

3. Shopping list generation

+
    +
  • Only the planner role can generate or regenerate the shopping list
  • +
  • Ingredients from ALL planned meals for the week are collected
  • +
  • Shared ingredients are merged and quantities summed (e.g. "Jasmine rice: 500g" from "Salmon teriyaki" + "Thai curry")
  • +
  • Pantry staples (defined in A3/D3) are automatically filtered out
  • +
  • The "For:" source line shows ALL recipes that use that ingredient
  • +
  • Filtered staples are listed in the recipe reference panel (desktop) for transparency
  • +
+ +

4. Real-time sync

+
/* Real-time rules:
+ * - is_checked updates broadcast to ALL connected clients instantly
+ * - "N members online" indicator shows who is currently viewing the shopping list
+ * - Prevents double-buying when multiple family members shop simultaneously or at different times
+ * - Blue accent colour for all shared-state UI:
+ *     Mobile: blue-tint banner with blue dot
+ *     Desktop: blue-tint badge in topbar with blue dot
+ * - WebSocket or SSE for real-time — implementation choice, but must be instant */
+ +

5. Custom items

+
    +
  • Any household member (planner or member) can add items not on the generated list
  • +
  • Use case: household supplies, snacks, items forgotten by the planner
  • +
  • Custom items appear at the bottom of the unchecked list
  • +
  • "+ Add custom item" link — blue-dark colour, centred (mobile) or left-aligned (desktop)
  • +
  • Custom items can be checked off and removed just like generated items
  • +
+ +

6. Data operations

+
/* Generate list:
+ *   SELECT ri.ingredient_id, i.name, SUM(ri.quantity), ri.unit
+ *   FROM recipe_ingredient ri
+ *   JOIN ingredient i ON ri.ingredient_id = i.id
+ *   JOIN week_plan_slot wps ON wps.recipe_id = ri.recipe_id
+ *   WHERE wps.week = :current_week
+ *     AND i.is_staple = false
+ *   GROUP BY ri.ingredient_id, i.name, ri.unit
+ *
+ * Check off:
+ *   UPDATE shopping_list_item
+ *   SET is_checked = true/false
+ *   WHERE id = :item_id
+ *   → broadcast change to all connected clients via real-time channel
+ *
+ * Add custom:
+ *   INSERT INTO shopping_list_item (name, quantity, is_custom, is_checked, shopping_list_id)
+ *   VALUES (:name, :quantity, true, false, :list_id)
+ *   → broadcast new item to all connected clients */
+ +

7. Design constraints

+
    +
  • List is ALWAYS live — no draft/publish workflow, no approval step
  • +
  • Both planner and member can: view, check off, add custom items, remove items
  • +
  • Only planner can: generate list, regenerate list
  • +
  • "Edit staples" link navigates to D3 (same component as A3 — build once, reference from two entry points)
  • +
  • CalDAV export is future scope (E3) — do not build in v1
  • +
  • Recipe reference panel is a page section with surface bg — NOT a floating card
  • +
  • Blue accent colour is reserved for shared/collaborative state indicators
  • +
  • Checked items must visually separate from unchecked via a divider and "Checked off" label
  • +
+ +

8. Preconditions

+
/* Precondition chain:
+ * J1 (recipes exist) — cannot generate a shopping list without recipes
+ * J2 (week is planned) — cannot generate a shopping list without planned meals
+ * J6 (household setup) — required for shared access (multiple members online)
+ *
+ * If no meals are planned: show empty state on D1 with prompt to plan the week first
+ * If no household members: list works for solo planner, shared banner is hidden */
+
+ + +
+ + \ No newline at end of file diff --git a/specs/frontend/j6-household-setup.html b/specs/frontend/j6-household-setup.html new file mode 100644 index 0000000..1a66208 --- /dev/null +++ b/specs/frontend/j6-household-setup.html @@ -0,0 +1,472 @@ + + + + + + J6 — Household Setup · Screen Specs + + + + +
+ +
+
+

J6 — Household setup

+

One-time onboarding journey · Screens A1, A2, A3/D3, A4

+
+
+ v1.0
+ Screens: 4
+ Flow: A1 → A2 → A3 → A2 → [invite] → A4 +
+
+ +
+
J6
+

Household setup

One-time onboarding. Account creation → household naming → staples → invite.

A1 → A2 → A3 → A2 → [invite] → A4
+
+ + +
+

Sign up

A1
+
First screen. Creates user_account. No navigation chrome (pre-auth). Desktop: full-viewport split — brand identity left, signup form right. Not a centered card — the brand section fills the entire left half.
+
V2 · Split layout — brand left fills viewport height, form right
+ +
+
+
Mobile · 320px
+
+
9:41●●● WiFi 🔋
+
+
+
🥗
+
Mealplan
+
Plan meals, eat well, waste less
+
+
+
Create your account
+
You'll set up your household next.
+
+
+
+ +
Already have an account? Log in
+
+
+
+
+
+
Desktop · 1040px
+
+
+
🥗
+
Mealplan
+
Plan your week's dinners. Get variety-aware suggestions. Shop together as a household.
+
+
📅
Plan
+
🍳
Cook
+
🛒
Shop
+
+
+
+
+
Create your account
+
You'll set up your household next.
+
+
+
+ +
Already have an account? Log in
+
+
+
+
+
+
+

A1 · Sign up

+
/* Pre-auth. No nav chrome. Desktop: full-viewport 2-col split. Brand ~42% / Form ~58%.
+ * Mobile: brand as ~120px banner, form below.
+ * Brand section: green-dark bg. Contains logo, tagline, 3 feature icons.
+ * Form section: page bg. Form max-width 380px. Not a card — just content on the page.
+ * Writes: user_account INSERT → redirect A2 */
+ + + + + + + + + +
ElementValueNotes
Desktop layout
Brand panel440px fixed, green-dark bg, content centered verticallyLogo 64px + name Fraunces 36px + tagline 15px + 3 feature icons
Form panelflex:1, page bg, content centered vertically, 48px 56px paddingForm max-width 380px. Not wrapped in a card.
Mobile layout
Brand banner~120px, green-dark bg, centeredLogo 28px + name 22px + tagline 12px
FormFull width, 24px 20px paddingSame fields, smaller type sizes
Data
Writesuser_account INSERTsystem_role='user', is_active=true → A2
+
+
+ + +
+

Household setup

A2
+
Name household + optional member invite. Desktop: full-page layout with a left illustration/progress column and the form on the right. Not a floating card — a structured page with clear sections.
+
V1 · Simple form — desktop: progress sidebar left, form right
+ +
+
+
Mobile · 320px
+
+
9:42●●● WiFi 🔋
+
+
+
Step 1 of 3
+
Name your household
+
This appears in the sidebar and is shared with all members.
+
+
+
Invite members (optional)
+
You can skip this and invite people later from settings.
+ +
+
+
+
+
+
+
+
Desktop · 1040px
+
+ +
+
+
🥗
+
Mealplan
+
+ +
+
+
1
+
Name your household
Give your family a name
+
+
+
2
+
Set up pantry staples
What you always have at home
+
+
+
3
+
Invite members
Share with your household
+
+
+
+ +
+
+
Name your household
+
This name appears in the sidebar and is shared with all members.
+
+
+
Invite members (optional)
+
You can skip this and invite people later from settings.
+ +
+
+
+
+
+
+
+
+

A2 · Household setup

+
/* Desktop: progress sidebar (300px, surface bg) + form area (flex:1, page bg).
+ * Progress sidebar shows: app logo + 3 numbered steps (current = green circle, future = subtle).
+ * Form area: content centered vertically, max-width 420px. Not a card — content on page bg.
+ * Mobile: full-width form with step indicator text at top. No progress sidebar.
+ * Writes: household INSERT + household_member INSERT (role=planner) → A3 */
+ + + + + + + + +
ElementValueNotes
Desktop layout
Progress sidebar300px, surface bg, border-rightApp logo top + numbered steps. Current step: green circle.
Form areaflex:1, page bg, centered contentmax-width 420px. Larger input (16px, 12px padding).
Step circles28px diameter. Active: green bg #fff text. Future: subtle bg muted text.Labels: 13px name + 11px description below
Mobile
Step indicator"Step 1 of 3" eyebrow textNo sidebar, text-only progress
FormFull width, 24px 20px paddingSame fields
+
+
+ + + +
+

Pantry staples

A3 / D3
+
Toggle staple ingredients by category. Desktop: same progress sidebar as A2 (step 2 active) + content area with a multi-column chip grid. The chips flow naturally across the full content width — no card wrapper needed.
+
V2 · Categorized list — desktop: progress sidebar + 2-col category grid
+ +
+
+
Mobile · 320px
+
+
9:43●●● WiFi 🔋
+
+
+
Step 2 of 3
+
Your pantry staples
+
These won't appear on your shopping list. Tap to toggle.
+
Oils & fats
+
Olive oilButterCoconut oil
+
Spices
+
SaltPepperGarlicCuminPaprika
+
Grains & pasta
+
RicePastaFlour
+
Sauces
+
Soy sauceFish sauceVinegar
+
+
+
+
+
+
+
Desktop · 1040px
+
+ +
+
🥗
Mealplan
+
+
Name your household
Smith family
+
2
Set up pantry staples
What you always have at home
+
3
Invite members
+
+
+ +
+
Your pantry staples
+
These items won't appear on your shopping list. Click to toggle. You can always change these later in settings.
+
+
Oils & fats
Olive oilButterCoconut oilVegetable oil
+
Spices & seasonings
SaltPepperGarlicCuminPaprikaChili flakesOreganoCinnamon
+
Grains & pasta
RicePastaFlourBreadcrumbsCouscous
+
Sauces & condiments
Soy sauceFish sauceVinegarMustardKetchup
+
Baking
SugarBaking powderVanilla extract
+
Dairy & basics
EggsMilkCreamCheese
+
+ +
Skip for now
+
+
+
+
+
+

A3/D3 · Pantry staples

+
/* Desktop onboarding: progress sidebar (300px, step 2 active) + content area with 2-col category grid.
+ * Categories flow in a CSS grid (2 columns, 24px row gap, 32px col gap).
+ * Chips sit directly on the page bg — no card wrappers.
+ * Desktop settings (D3): same chip grid but inside sidebar+topbar layout (no progress sidebar).
+ * Mobile: single-column chip list, full width.
+ * Chip toggle: UPDATE ingredient SET is_staple. Debounced 300ms. */
+ + + + + + + +
ElementValueNotes
Desktop onboarding
Progress sidebar300px, surface bg. Step 1 = ✓ completed. Step 2 = green active.Same sidebar as A2, reused component.
Category gridgrid-template-columns: 1fr 1fr. gap: 24px 32px.Categories from ingredient_category, sorted by sort_order.
Chips12px/500, 6px 12px pad, 20px radius. Selected: green-tint/green-light/green-dark.Direct on page bg. No card wrapper.
Desktop settings (D3)
LayoutApp sidebar (224px) + topbar ("Staples") + content with 3-col gridWider content area → 3 columns for categories.
+
+
+ + + +
+

Join household

A4
+
Member accepts invite. Desktop: split layout like A1 — left side shows the household identity (name, who invited), right side has the signup form. The left panel uses green-tint (not green-dark) since this is a welcoming join screen, not a brand-first screen.
+
V2 · Welcome card — desktop: household identity left, join form right
+ +
+
+
Mobile · 320px
+
+
10:15●●● WiFi 🔋
+
+
+
🥗
+
Smith family
+
Sarah invited you to join their meal planner
+
+
+
You'll be able to view the weekly meal plan and check off items on the shared shopping list.
+
+
+
+ +
+
+
+
+
+
Desktop · 1040px
+
+ +
+
🥗
+
Smith family
+
Sarah invited you to join
+
+
What you'll be able to do:
+
+
📅 View the weekly meal plan
+
🛒 Check off shopping list items
+
➕ Add items to the list
+
+
+
+ +
+
+
Join the household
+
Create your account to get started.
+
+
+
+ +
Already have an account? Log in instead
+
+
+
+
+
+
+

A4 · Join household

+
/* Desktop: split layout. Left (400px, green-tint bg): household identity + permissions list.
+ * Right (flex:1, page bg): signup form max-width 380px.
+ * Left panel uses green-tint (welcoming) not green-dark (brand-first).
+ * Mobile: green-tint banner at top + form below.
+ * Transaction: user_account INSERT + household_member INSERT (role=member) + household_invite UPDATE → C1 */
+ + + + +
ElementValueNotes
Desktop
Identity panel400px, green-tint bg, centered contentLogo 64px + name Fraunces 32px + inviter + permissions list
Form panelflex:1, page bg, max-width 380pxSame signup fields as A1
+
+
+ + +
+

Implementation Guide — J6 Household Setup

+

This journey is completed once when the app is first used. The planner creates an account, names the household, defines pantry staples, and invites household members.

+ +

Journey Flow

+
    +
  1. A1 — Sign up: New user creates account with name, email, password. Writes user_account → redirects to A2.
  2. +
  3. A2 — Household setup: Planner names household (e.g. "Smith family"), optionally generates invite link. Writes household + household_member (role=planner) → redirects to A3.
  4. +
  5. A3 — Pantry staples: Toggle staple ingredients by category. Debounced 300ms save. Updates ingredient.is_staple. Same component as D3 in settings.
  6. +
  7. A4 — Join household: Invited member opens link, sees household identity, creates account. Writes user_account + household_member (role=member) + updates household_invite → redirects to C1.
  8. +
+ +

Roles

+ + + + +
RoleCreated atAccess
plannerA2 (automatic)Full access to all 15 screens
memberA4 (on invite accept)C1 read-only + D1 view/check/add
+ +

Layout Rules

+
    +
  • All screens are pre-auth — no sidebar, no tab bar, no navigation chrome.
  • +
  • A1, A4 desktop: Full-viewport 2-column split. Brand/identity left (fixed width), form right (flex:1).
  • +
  • A2, A3 desktop: Progress sidebar (300px) left + form/content right (flex:1).
  • +
  • Mobile: All screens are stacked single-column. Brand/identity as a banner at top, form below.
  • +
+ +

Design Constraints

+
    +
  • A1 brand panel: --green-dark bg (brand-first). A4 identity panel: --green-tint bg (welcoming).
  • +
  • A3 = D3 — single component, two contexts. Onboarding (progress sidebar + 2-col grid) vs settings (app sidebar + 3-col grid).
  • +
  • Chip toggle: selected = --green-tint bg + --green-light border + --green-dark text.
  • +
  • Progress steps: current = green circle, completed = green-tint + checkmark, future = subtle circle.
  • +
  • Invite mechanism: link or short code. No in-app email system. Planner shares via messaging app.
  • +
  • Form max-width: 380px (A1, A4) or 420px (A2). Never wider.
  • +
+ +

Data Operations

+ + + + + + +
ScreenWritesReads
A1user_account INSERT
A2household INSERT, household_member INSERT (role=planner), household_invite INSERT (optional)
A3/D3ingredient UPDATE (is_staple) — debounced 300msingredient SELECT grouped by ingredient_category
A4user_account INSERT, household_member INSERT (role=member), household_invite UPDATEhousehold_invite SELECT (validates code), household SELECT (name, inviter)
+ +

Accessibility

+
    +
  • All forms: semantic <form>, <label> with for, visible focus indicators.
  • +
  • Chip toggles (A3): use role="checkbox" or <input type="checkbox"> with visual styling.
  • +
  • Progress steps (A2, A3): use aria-current="step" on the active step.
  • +
  • Contrast: all text meets WCAG 2.2 AA (4.5:1 normal, 3:1 large).
  • +
+ +

Preconditions & Dependencies

+
    +
  • J6 is a precondition for all other journeys — user must have an account and household.
  • +
  • J6 is a precondition for J5 shared list — household members must be invited before the list is shared.
  • +
  • A3 configures staples that J5 (shopping list) uses for smart filtering.
  • +
  • No other screens are accessible to household members in v1 besides C1 (read-only) and D1.
  • +
+
+ +
+ +