Public Access
docs: add complete project documentation
- 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.
This commit is contained in:
@@ -0,0 +1,542 @@
|
||||
# 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
|
||||
- [ ] Create ingredient matching service
|
||||
- [ ] Map recipe ingredients to `ingredient` table 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 `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
|
||||
Reference in New Issue
Block a user