28f321298fb71086664427888fcca691ae1f608b
Lifts the 'no new npm deps' rule for testing-only. Locks the
S9 bug class (onComplete → reset, the original bug from
1562929) with 7 unit tests in 25 ms.
5 changes:
- frontend/package.json — 4 new devDeps: vitest@^1.6.0,
happy-dom@^14.7.0, @testing-library/react@^14.2.0,
@testing-library/jest-dom@^6.4.0. Plus @types/node@^20
for tsc (Case 7's static check on App.tsx uses node:fs).
- frontend/package.json scripts — adds 'test' (vitest run,
no watch, CI-friendly) and 'test:watch' (vitest).
- frontend/vitest.config.ts (NEW) — defineConfig from
vitest/config, happy-dom env, setupFiles points to
vitest-setup.ts, include is src/**/*.test.{ts,tsx}.
- frontend/vitest-setup.ts (NEW) — one line: imports
@testing-library/jest-dom/vitest, auto-extends expect.
- frontend/src/components/OnboardingTour.test.tsx (NEW) —
7 cases:
1. clean init (localStorage empty) → isComplete=false.
2. persisted init (key = '1') → isComplete=true.
3. markComplete → state=true, localStorage STAYS at '1'
(locks one direction of the S9 bug at the hook level).
4. reset → localStorage cleared + state=false.
5. show → mirror of reset (intentional).
6. localStorage throw on read → silently swallowed,
isComplete=false, no crash.
7. App.tsx wiring — static check: onComplete calls
markComplete, onReset calls reset, neither inverts.
Case 7 is the load-bearing test: Sprint 9's bug was
at the App.tsx call site, not in the hook, so Cases
1-6 cannot catch it. Case 7 reads App.tsx as a string
via node:fs/promises, regex-matches the arrow bodies
of onComplete={...} and onReset={...}, asserts each
calls the right onboarding.* method.
Verified: flipping markComplete → reset in App.tsx makes
Case 7 fail on the onCompleteBody.toMatch(/markComplete/)
assertion. All 7 cases pass in 25 ms. npm run build green
(tsc 0 errors, vite built in 2.6 s, bundle 503.82 kB
unchanged — vitest is devDeps only). No backend change.
No migration. No runtime dep change.
Deploy: git pull + cd frontend && npm install && npm test
(confirm 7/7) + cd .. && docker compose up -d --build
frontend. No backend rebuild.
Meal Planner
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.
Background
This project was born out of frustration with meal kit services (Blue Apron → EveryPlate → HungryRoot → Sunbasket) that:
- Escalate costs to 3x ingredient markup
- Fall into repetitive meal rhythms
- Force users to log into apps to manage selections
- Don't integrate with home pantry items
Features
- Grocery Integration: Scrapes Lucky California weekly ads and sales
- Family Approval Workflow: Email proposals with approve/deny; one denial swaps the meal
- Shopping List Generation: Weekly list grouped by store aisles, highlighting sales, with interactive checkboxes to track purchased items
- Pantry Integration: Specify home items to incorporate into suggestions
- Web UI: Modern interface for the whole family
- Learning: Feedback-based meal recommendations, with weekly auto-discovery of new recipes from external APIs when family preferences are signaled
- Recipe Images: Scraped from public recipe sites, AI fallback available
- Unit Conversion: Converts recipe quantities (cups, tbsp, lb) to grocery units for accurate cost estimates
Architecture
- Backend: Python/FastAPI
- Database: PostgreSQL
- Frontend: React + Tailwind CSS
- Email: SendGrid
- Hosting: Docker Compose with nginx reverse proxy
Documentation
Quick Start
# Clone and start
docker-compose up -d
# View logs
docker-compose logs -f
# Stop
docker-compose down
Family Profile
Household: 2 adults, 2 children
- One adult likes mushrooms, one child OK with them
- Three family members do NOT like mushrooms
- No allergies
- Calorie, budget, and health conscious eating
Approval Workflow
- System generates 7-day meal plan based on sales, dietary constraints, budget, variety
- Email sent to both adults with meal previews
- One denial = meal swapped; no denials = auto-approved
- Shopping list generated after approval
Tech Stack
| Component | Technology |
|---|---|
| Backend | Python 3.11, FastAPI |
| Database | PostgreSQL 15 |
| Frontend | React 18, TypeScript, Tailwind |
| Scraping | Playwright, BeautifulSoup |
| SendGrid | |
| Hosting | Docker Compose, nginx |
Languages
Python
72.5%
TypeScript
25.9%
JavaScript
0.5%
PLpgSQL
0.4%
CSS
0.3%
Other
0.2%