- SPEC.md: project specification and goals - ARCHITECTURE.md: system design and component descriptions - database-schema.md: PostgreSQL schema with all tables - implementation-plan.md: 12-phase implementation guide - RUNNING.md: deployment and troubleshooting guide - ORIENTATION.md: context compaction recovery guide - README.md: project overview and quick start Family profile: 2 adults, 2 children. Mushroom avoidance for 3/4. Approval workflow: email proposals, one denial swaps meal. Tech stack: FastAPI, PostgreSQL, React, Playwright, SendGrid.
15 KiB
Meal Planner - Implementation Plan
Overview
Self-hosted meal planning system that integrates with Lucky California grocery store, sends weekly meal proposals via email to family members, generates shopping lists, and learns from feedback.
Phase 1: Infrastructure & Foundation
1.1 Project Setup
- Initialize Git repository with
.gitignore(Python, Node, Docker) - Create
docker-compose.ymlwith: backend (FastAPI), frontend (React), PostgreSQL, nginx - Create
backend/directory structure - Create
frontend/directory structure - Set up Alembic for database migrations
- Create initial database migration with full schema
Verify: docker-compose up -d starts all services; docker-compose ps shows all running
1.2 Backend Skeleton
- Create FastAPI app with directory structure:
backend/app/ __init__.py main.py config.py database.py models/ schemas/ api/ services/ scraper/ - Create SQLAlchemy models matching database schema
- Create Pydantic schemas for API requests/responses
- Set up database connection with session management
- Create health check endpoint
GET /health
Verify: curl localhost:8000/health returns {"status": "ok"}
1.3 Frontend Skeleton
- Create React app with TypeScript (
npx create-react-appor Vite) - Install dependencies: Tailwind CSS, React Router, React Query, Axios
- Create basic directory structure:
frontend/src/ components/ pages/ hooks/ api/ types/ - Set up React Query provider and routing
- Create basic layout with navigation
Verify: Frontend builds without errors; docker-compose up serves frontend on port 3000
1.4 Reverse Proxy (Nginx)
- Create
nginx.confwith routing rules:/api/*→ backend:8000/*→ frontend:80- SSL configuration for remote access
- Create Caddyfile alternative for easier Let's Encrypt setup
Verify: Nginx starts without config errors; routing works correctly
Phase 2: Database & Models
2.1 SQLAlchemy Models
- Create
backend/app/models/__init__.pywith all model imports - Implement
FamilyProfilemodel - Implement
Ingredientmodel - Implement
Recipemodel with JSONB ingredients column - Implement
MealPlanmodel - Implement
MealPlanItemmodel - Implement
HomePantrymodel - Implement
Feedbackmodel - Implement
NeverSuggestmodel - Implement
GroceryItemmodel - Implement
ScrapeLogmodel - Implement
EmailLogmodel
2.2 Pydantic Schemas
- Create request/response schemas for each model
- Create nested schemas for related objects (e.g.,
MealPlanWithItems) - Create pagination schemas for list endpoints
2.3 Database Migrations
- Create Alembic configuration
- Create initial migration from SQLAlchemy models
- Add seed data migration (basic ingredients, sample recipes)
Verify: alembic upgrade head runs without errors; tables created in PostgreSQL
Phase 3: API Endpoints
3.1 Core CRUD Endpoints
GET/PUT /api/profile- Family profile managementGET/POST /api/ingredients- Ingredient listGET/POST /api/recipes- Recipe managementGET /api/recipes/{id}- Single recipe with full detailsGET /api/pantry- Home pantry itemsPOST/DELETE /api/pantry/{id}- Add/remove pantry items
3.2 Meal Plan Endpoints
GET /api/meals/planned- Current week's meal planPOST /api/meals/{id}/approve- Approve a mealGET /api/deny/{token}- Denial form (for email links)POST /api/deny/{token}- Process denial with reason
3.3 Shopping List Endpoints
GET /api/shopping-list- Current week's shopping listGET /api/shopping-list/print- Printable format (PDF-ready HTML)
3.4 Feedback Endpoints
POST /api/feedback- Submit feedback for a mealGET /api/feedback- View feedback history
3.5 Admin Endpoints
POST /api/admin/scrape- Trigger Lucky California scrapeGET /api/admin/logs- View scrape and email logs
Verify: All endpoints return expected status codes and data shapes
Phase 4: Lucky California Scraper
4.1 Scraper Infrastructure
- Create
backend/app/scraper/base.pywith base scraper class - Create
backend/app/scraper/playwright_setup.pyfor browser automation - Implement retry logic with exponential backoff
- Create logging for scrape operations
- Implement rate limiting (respect Lucky California's limits)
4.2 Weekly Ad Scraper
- Scrape Lucky California homepage for weekly ad link
- Parse weekly ad page for sale items
- Extract: product name, sale price, regular price, image URL, product URL
- Map products to existing ingredients or create new ones
- Store in
grocery_itemtable
4.3 Product Catalog Scraper (Future)
- Scrape product search results for specific ingredients
- Parse product detail pages for pricing and availability
- Implement pagination handling
4.4 Scrape Scheduling
- Create scheduler service (APScheduler or similar)
- Schedule weekly scrape (Sunday night before meal planning)
- Schedule ad-hoc scrape via admin endpoint
4.5 Error Handling
- Log all scrape failures with full context
- Create alert if scrape fails 3 consecutive times
- Store failed URLs for manual review
Verify: Scraper successfully pulls 10+ sale items from Lucky California website
Phase 5: Recipe Engine
5.1 Recipe Database
- Create recipe CRUD service
- Implement tag-based filtering (cuisine, dietary, protein)
- Create search functionality (name, ingredients)
- Store recipe images (URL reference)
5.2 Recipe Importing
- Create basic recipe input form in web UI
- Support manual recipe entry (name, ingredients, instructions)
- Support pasting recipe URL for future scraping
5.3 Ingredient Mapping
- Create ingredient matching service
- Map recipe ingredients to
ingredienttable entries - Handle unit conversions (cups → oz, etc.)
Verify: Can add a recipe manually and retrieve it via API
Phase 6: Meal Planner Engine
6.1 Plan Generation Algorithm
- Create
MealPlannerServicewith generation logic - Load constraints: family profile, dietary restrictions, budget
- Filter out
never_suggestingredients and recipes - Prioritize ingredients from
home_pantry - Select meals based on variety (max 2 same protein/sauce per week)
- Incorporate sale items from
grocery_item - Generate 7-day plan (dinner only for MVP)
6.2 Substitution Logic
- When meal denied, find similar substitute
- Criteria: same protein, similar cuisine, within budget
- Avoid previously denied meals
6.3 Cost Calculation
- Calculate per-serving cost using grocery prices
- Sum total weekly meal cost
- Flag meals exceeding budget
6.4 Plan Persistence
- Save generated plan as
draftstatus - Generate unique approval tokens per meal
- Set approval deadline (48h from email send)
Verify: Plan generation produces valid 7-day plan respecting all constraints
Phase 7: SendGrid Email Integration
7.1 SendGrid Setup
- Create SendGrid API key (if not already done)
- Create
backend/app/services/email_service.py - Implement email sending via SendGrid API
- Create HTML email templates
7.2 Meal Proposal Email
- Create email template with:
- Week overview
- All 7 meals listed with images
- Each meal: name, day, image, ingredients list, cost estimate
- Approve/Deny links with tokens
- Deadline reminder
- Send to both adult email addresses
7.3 Reminder Email
- Send reminder 2 days before deadline
- Include current approval status
- Include link to web UI for approval
7.4 Confirmation Email
- Send after all meals approved
- Include link to shopping list
- Include link to recipes
Verify: Emails sent and received; links work correctly
Phase 8: Web UI - Core Features
8.1 Dashboard
- Create
Dashboardpage - Show current week's meal plan
- Show approval status for each meal
- Quick action buttons (approve/deny)
- Show shopping list summary
8.2 Meal Detail Page
- Create
MealDetailpage - Show full recipe with ingredients and instructions
- Display meal image
- Show nutritional hints (calories, protein)
- Print recipe button
8.3 Approval Center
- Create
ApprovalCenterpage - List pending approvals
- Approve/Deny buttons with reason selection
- Show denial history and reasons
8.4 Pantry Manager
- Create
PantryManagerpage - Add items with quantity and unit
- Remove items
- Set expiration dates for perishables
Verify: All pages render correctly; actions update database
Phase 9: Web UI - Feedback & Learning
9.1 Feedback Portal
- Create
FeedbackPortalpage - Rate completed meals (1-5 stars)
- Select "Never suggest this" option
- Free-text feedback field
9.2 Learning Integration
- Update meal planner weights based on feedback
- Block denied recipes from future proposals
- Block denied ingredients from future proposals
9.3 Recipe Discovery
- Create
RecipeBrowserpage - Filter by cuisine, protein, dietary tags
- Search by name or ingredient
- "Surprise me" random recipe button
Verify: Feedback submitted and reflected in future meal plans
Phase 10: Shopping List & Print
10.1 Shopping List Generation
- Aggregate all ingredients from week's meals
- Subtract home pantry items
- Group by Lucky California aisle
- Highlight sale items
- Show estimated total cost
10.2 Printable Shopping List
- Create print-optimized CSS
- Generate clean HTML for printing
- Include checkbox squares for manual marking
- Show aisle location for each item
10.3 Web UI Shopping List View
- Create
ShoppingListpage - Show items grouped by aisle
- Show sale price vs regular price
- Show total estimated cost
- Print/export button
Verify: Shopping list accuracy (matches meal plan ingredients minus pantry)
Phase 11: Image Strategy Implementation
11.1 Scraped Images
- Store image URLs in
recipe.image_url - Implement graceful fallback if image unavailable
- Lazy-load images in web UI
11.2 AI Image Generation (Fallback)
- Create AI image service abstraction
- Implement DALL-E or similar API integration
- Generate images only when scraped image unavailable
- Cache generated images in database
- Add config flag to enable/disable AI generation
11.3 Email Image Handling
- Embed images via CDN URL or inline base64
- Provide alt text for blocked images
- Include link to web UI for full image gallery
Verify: Meals display appropriate images in both web UI and email
Phase 12: Polish & Future Features
12.1 Variety Analysis
- Track sauce/ingredient usage per week
- Warn if meals are too similar
- Suggest diverse alternatives
12.2 Budget Tracking
- Track actual spending vs estimated
- Show cost per serving over time
- Alert if significantly over budget
12.3 WhatsApp Integration (Future)
- Set up Twilio WhatsApp Business API
- Create WhatsApp message templates
- Implement approval/denial via WhatsApp
12.4 Recipe Scraping (Future)
- Implement recipe site scraper
- Parse recipe structured data (JSON-LD)
- Auto-import recipes from web
Verification Commands
Backend Tests
# Health check
curl localhost:8000/health
# API tests
curl localhost:8000/api/profile
curl localhost:8000/api/recipes
curl localhost:8000/api/shopping-list
Frontend Tests
# Build test
cd frontend && npm run build
# Dev server
cd frontend && npm run dev
Full Stack Tests
# Start all services
docker-compose up -d
# Check all services running
docker-compose ps
# View logs
docker-compose logs -f
# Stop all services
docker-compose down
File Structure
mealplanner/
├── docker-compose.yml
├── docker-compose.override.yml
├── .env.example
├── .gitignore
├── README.md
├── RUNNING.md
├── docs/
│ ├── SPEC.md
│ ├── ARCHITECTURE.md
│ ├── database-schema.md
│ └── implemenation-plan.md
├── nginx/
│ ├── nginx.conf
│ └── ssl/
├── backend/
│ ├── Dockerfile
│ ├── requirements.txt
│ ├── alembic.ini
│ ├── alembic/
│ │ ├── env.py
│ │ └── versions/
│ └── app/
│ ├── __init__.py
│ ├── main.py
│ ├── config.py
│ ├── database.py
│ ├── models/
│ │ ├── __init__.py
│ │ └── [model files]
│ ├── schemas/
│ │ ├── __init__.py
│ │ └── [schema files]
│ ├── api/
│ │ ├── __init__.py
│ │ └── [endpoint files]
│ ├── services/
│ │ ├── __init__.py
│ │ ├── email_service.py
│ │ ├── meal_planner_service.py
│ │ └── [other services]
│ └── scraper/
│ ├── __init__.py
│ ├── base.py
│ ├── lucky_ca_scraper.py
│ └── [other scrapers]
└── frontend/
├── Dockerfile
├── package.json
├── vite.config.ts
├── tailwind.config.js
└── src/
├── App.tsx
├── main.tsx
├── index.css
├── components/
├── pages/
├── hooks/
├── api/
└── types/
Dependencies
Backend (Python 3.11+)
- fastapi
- uvicorn
- sqlalchemy
- alembic
- psycopg2-binary
- pydantic
- sendgrid (sendgrid-python)
- playwright
- beautifulsoup4
- apscheduler
- python-dotenv
- pytest (dev)
Frontend (Node 18+)
- react
- react-dom
- react-router-dom
- @tanstack/react-query
- axios
- tailwindcss
- postcss
- autoprefixer
- typescript
- vite
- @types/react
- @types/node
Environment Variables
# Backend
DATABASE_URL=postgresql://mealplanner:password@db:5432/mealplanner
SENDGRID_API_KEY=SG.xxx
RECIPES_EMAIL=you@example.com
FAMILY_EMAIL_1=wife@example.com
FAMILY_EMAIL_2=you@example.com
AI_IMAGE_ENABLED=false
AI_IMAGE_PROVIDER=openai
# Frontend
VITE_API_URL=http://localhost:8000
# Docker
POSTGRES_PASSWORD=secure_password_here
Notes
- All code commits should follow conventional commit format
- Test at each phase before proceeding to next
- Document any deviations from this plan
- Keep ORIENTATION.md updated as implementation progresses