Files
Meal-Planner/docs/SPEC.md
T
admin a0b16f7418 fix: address adversarial review blockers
All §1 consensus blockers and §2 high-risk gaps resolved:

Schema fixes:
- Remove RecipeIngredient join table, use JSONB for ingredients
- Add family_member table for per-voter approval tracking
- Add all ENUMs for status fields (no loose VARCHAR)
- Add CHECK constraints (household_size, rating 1-5, day_of_week)
- Add name_lower for case-insensitive ingredient matching
- Add grocery_item → ingredient FK
- Fix day_of_week to ISO-8601 (1=Monday, 7=Sunday)
- Remove calorie_target (nutrition is non-goal)

Approval flow redesign:
- Email link → confirmation page (GET), not auto-approve
- Actual vote is POST from confirmation page
- Per-voter tokens (single-use, 72h TTL)
- Record which member voted

Auth model:
- VPN-only for admin endpoints
- Session-based for family web UI

Docker hardening:
- Remove direct port exposure for backend/frontend
- nginx is sole entrypoint
- Add docker-compose.dev.yml for local dev

Skeleton fixes:
- Add missing Pantry.tsx page
- Add missing index.html (Vite entrypoint)
- Add package-lock.json
- Fix SQLAlchemy 2 text() for raw SQL
- Remove create_all from startup (use migrations)
- Configure Alembic properly

Docs updates:
- Update Lucky URL to luckysupermarkets.com
- Add WCAG 2.1 AA accessibility target
- Update family profile with correct mushroom preferences
- Add external dependencies list to SPEC

Verification:
- docker compose config: PASS
- docker compose build backend: PASS
- docker compose build frontend: PASS
- backend import: PASS
- alembic context: PASS
2026-05-04 20:11:05 -07:00

8.1 KiB

Meal Planner - Project Specification

1. Overview

Project Name: MealPlanner Type: Self-hosted meal planning system Core Functionality: Weekly meal plan generation that integrates with Lucky California grocery sales, sends approval requests to family members via email, generates shopping lists, and learns from feedback. Target Users: A family of 4 (2 adults, 2 children) seeking to optimize meal planning for cost, health, and variety.


2. Problem Statement

Current meal kit services (Blue Apron → EveryPlate → HungryRoot → Sunbasket) suffer from:

  • Escalating costs (3x ingredient markup)
  • Repetitive meals and sauces
  • Forcing users to log into apps to manage meal selection
  • No offline pantry integration

Desired Solution: A self-hosted system that:

  • Sources ingredients from local grocery store (Lucky California) sales and in-season products
  • Proposes meals via email with approval workflow
  • Generates actionable shopping lists
  • Incorporates existing home pantry items
  • Learns from family feedback over time

3. Goals

Primary Goals

  1. Weekly Meal Planning: Automatically generate a 7-day meal plan each week
  2. Grocery Integration: Scrape Lucky California weekly ads and product catalog for sales/in-season items
  3. Family Approval Workflow: Send email to adults with meal proposal, image, and details; one denial swaps the meal
  4. Shopping List Generation: Create weekly shopping list grouped by Lucky California aisles, highlighting sales
  5. Pantry Integration: Allow users to specify items they have at home to incorporate into meal suggestions
  6. Web UI: Modern interface for non-technical family members to interact with meals, feedback, and recipes
  7. Recipe & Image Generation: Display meal images and printable recipes

Secondary Goals

  1. Feedback Learning: System learns from "never suggest", ratings, and denial reasons
  2. Variety Analysis: Detect when meals fall into similar rhythms (same sauces/ingredients)
  3. Budget Optimization: Track and optimize meal costs per serving
  4. WhatsApp Integration: Future expansion via Twilio (out of scope for initial build)

4. Non-Goals (Out of Scope)

  • Actual online ordering/payment at Lucky California
  • Native mobile apps (responsive web UI only)
  • Recipe parsing from personal recipe collections (Paprika, etc.)
  • AI image generation as primary source (scraped images first)
  • Multi-language support
  • Nutrition tracking beyond high-level calorie awareness

5. User Stories

As a family member, I can:

  • Receive weekly email with proposed meals for the week
  • View meal details including: name, image, ingredients, cook time, servings
  • Approve or deny a meal with optional feedback reason
  • Access the web UI to adjust home pantry items
  • View printable recipe cards
  • Provide feedback on meals ("Loved it", "Too bland", "Never again")

As the system administrator, I can:

  • View scraping logs and debug failed scrapes
  • Adjust family profile settings (dietary restrictions, household size)
  • See meal plan approval history
  • Monitor system health via logs

6. Family Profile

Household

  • 2 adults, 2 children
  • Calorie, budget, and health conscious eating
  • Food should be tasty but not overly expensive

Family Members

Member Role Mushroom Preference
Adult 1 Adult Does NOT like mushrooms
Adult 2 Adult Likes mushrooms
Child 1 Child Does NOT like mushrooms
Child 2 Child OK with mushrooms

Dietary Constraints

  • 3 of 4 family members do NOT like mushrooms
  • No allergies

Preference Signals

  • "Never suggest this ingredient" flags (per family, not per member)
  • Per-meal ratings (1-5 stars, per member)
  • Denial reasons (too expensive, looks boring, contains disliked ingredient, etc.)
  • Home pantry items to incorporate

7. Approval Workflow

Weekly Flow

  1. System generates 7-day meal plan based on:

    • Lucky California sales and in-season items
    • Family dietary constraints (no mushrooms for 3/4 members)
    • Budget constraints
    • Variety requirements (avoid sauce/ingredient repetition)
    • Home pantry items to use
  2. Email sent to all adult family members containing:

    • All 7 meals listed with images
    • Each meal has: "View & Vote" link to web approval page
    • Email does NOT auto-approve on link click
  3. Approval page flow (Web UI):

    • Adult clicks email link → lands on confirmation page
    • Page shows meal details, image, ingredients, estimated cost
    • Adult clicks "Approve" or "Deny"
    • Denial requires selecting a reason
    • Vote is recorded per-member (not per-household)
  4. Approval handling:

    • If majority of adults approve → meal confirmed
    • If any adult denies → meal swapped with alternative suggestion
    • Denial reason is recorded for learning
    • Explicit deadline: 48 hours from email send
    • After deadline: meals with insufficient responses auto-expire and are excluded
  5. After approval period:

    • Final meal plan locked
    • Shopping list generated
    • Recipes made available in web UI

Approval Token Security

  • Each email contains a unique, single-use token per family member
  • Tokens expire after 72 hours
  • Tokens can only be used once (marked USED after voting)
  • Email links lead to a confirmation page; actual vote is a POST

8. Technical Constraints

Self-Hosting Requirements

  • Must run on local infrastructure (homelab, NUC, Synology, etc.)
  • Remote access via reverse proxy with VPN or TLS
  • Primary access: local network only (VPN required for remote)

Authentication & Authorization

  • Admin endpoints (/api/admin/*): VPN-only access
  • Family web UI: Session-based authentication (simple username/password)
  • Email approval links: Token-based, single-use, time-limited
  • No JWT; no OAuth

Lucky California Integration

  • URL: https://luckysupermarkets.com (verified)
  • Primary: Scrape weekly ad and product catalog
  • Store scraped data locally
  • Respect robots.txt and rate limiting
  • Fallback: Manual sale input if scraping fails

Email

  • SendGrid for transactional email
  • HTML email templates with meal images
  • Plain text fallback for email clients that block images
  • Accessible: includes alt text for images, works with screen readers

External Dependencies

Service Purpose Required
SendGrid Transactional email Yes
luckysupermarkets.com Grocery scraping Yes
Recipe websites Recipe images Yes
AI Image API (optional) Fallback image generation No

9. Accessibility (WCAG 2.1 AA)

Web UI

  • All interactive elements keyboard accessible
  • Color contrast ratio ≥ 4.5:1 for normal text
  • Form inputs have visible labels
  • Error messages are descriptive and associated with inputs
  • Skip navigation links provided

Email

  • HTML emails include meaningful alt text for all images
  • Plain text version provided as fallback
  • Links are descriptive (not "click here")
  • Font sizes are readable (minimum 14px equivalent)

10. Data Retention

Stored Data

  • All recipes (scraped and manually added)
  • Meal plans (weekly history)
  • Per-member votes and denial history
  • Feedback (ratings, flags, pantry items)
  • Scraped grocery data (weekly refresh)

Retention Period

  • Meal plans: 12 weeks rolling
  • Feedback: Indefinite (for learning)
  • Scraped grocery data: 2 weeks (to compare week-over-week)

11. Success Metrics

  1. Adoption: Family consistently uses the system weekly
  2. Meal variety: No more than 2 meals/week share the same sauce or primary protein
  3. Cost efficiency: Average cost per serving within 150% of equivalent grocery-store meal
  4. Explicit approval rate: >80% of proposed meals receive explicit approval (not silence)
  5. Learning: After 4 weeks, system should not propose previously denied meals

12. Future Considerations

  • Twilio WhatsApp integration for wife who prefers messaging
  • Direct Lucky California online ordering
  • Meal kit comparison (show cost difference vs. meal kit services)
  • Nutritional tracking (macros, sodium, etc.)
  • Grocery price history and trend analysis