Files
Meal-Planner/docs/implementation-plan.md
T
admin dcdb88595e docs: document unit conversion implementation
- Update implementation-plan.md: mark unit conversion complete
- Update HANDOFF.md: add session notes for 2026-05-24 unit conversion
- Update README.md: list Unit Conversion as a feature
2026-05-24 15:34:16 -07:00

546 lines
15 KiB
Markdown

# 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.yml` with: 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-app` or 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.conf` with 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__.py` with all model imports
- [ ] Implement `FamilyProfile` model
- [ ] Implement `Ingredient` model
- [ ] Implement `Recipe` model with JSONB ingredients column
- [ ] Implement `MealPlan` model
- [ ] Implement `MealPlanItem` model
- [ ] Implement `HomePantry` model
- [ ] Implement `Feedback` model
- [ ] Implement `NeverSuggest` model
- [ ] Implement `GroceryItem` model
- [ ] Implement `ScrapeLog` model
- [ ] Implement `EmailLog` model
### 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 management
- [ ] `GET/POST /api/ingredients` - Ingredient list
- [ ] `GET/POST /api/recipes` - Recipe management
- [ ] `GET /api/recipes/{id}` - Single recipe with full details
- [ ] `GET /api/pantry` - Home pantry items
- [ ] `POST/DELETE /api/pantry/{id}` - Add/remove pantry items
### 3.2 Meal Plan Endpoints
- [ ] `GET /api/meals/planned` - Current week's meal plan
- [ ] `POST /api/meals/{id}/approve` - Approve a meal
- [ ] `GET /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 list
- [ ] `GET /api/shopping-list/print` - Printable format (PDF-ready HTML)
### 3.4 Feedback Endpoints
- [ ] `POST /api/feedback` - Submit feedback for a meal
- [ ] `GET /api/feedback` - View feedback history
### 3.5 Admin Endpoints
- [ ] `POST /api/admin/scrape` - Trigger Lucky California scrape
- [ ] `GET /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.py` with base scraper class
- [ ] Create `backend/app/scraper/playwright_setup.py` for 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_item` table
### 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
- [x] Create ingredient matching service
- [x] Map recipe ingredients to `ingredient` table entries
- [x] Handle unit conversions (cups → oz, lb → g, etc.)
- Implemented in `app/utils/units.py`: normalization, within-family (weight/volume/count), cross-family via density tables for ~30 canonical ingredients, fallback to dimensionless
- Integrated into `planner/cost.py` for accurate cost calculation
- Orchestrator email and shopping list use converted quantities
**Verify**: Can add a recipe manually and retrieve it via API
---
## Phase 6: Meal Planner Engine
### 6.1 Plan Generation Algorithm
- [ ] Create `MealPlannerService` with generation logic
- [ ] Load constraints: family profile, dietary restrictions, budget
- [ ] Filter out `never_suggest` ingredients 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 `draft` status
- [ ] 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 `Dashboard` page
- [ ] 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 `MealDetail` page
- [ ] Show full recipe with ingredients and instructions
- [ ] Display meal image
- [ ] Show nutritional hints (calories, protein)
- [ ] Print recipe button
### 8.3 Approval Center
- [ ] Create `ApprovalCenter` page
- [ ] List pending approvals
- [ ] Approve/Deny buttons with reason selection
- [ ] Show denial history and reasons
### 8.4 Pantry Manager
- [ ] Create `PantryManager` page
- [ ] 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 `FeedbackPortal` page
- [ ] 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 `RecipeBrowser` page
- [ ] 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 `ShoppingList` page
- [ ] 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
```bash
# 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
```bash
# Build test
cd frontend && npm run build
# Dev server
cd frontend && npm run dev
```
### Full Stack Tests
```bash
# 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
```bash
# 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