End-to-end grocery automation: van recepten naar een gevulde AH-winkelwagen.
Receptendatabase ──> Menuplanner ──> Boodschappenlijst ──> AH-integratie
^
│
Voorraadbeheer
Web UI (FastAPI + HTMX + Tailwind)
└── Verbindt alle componenten in een browser-interface
| Component | Status | Beschrijving |
|---|---|---|
| Receptendatabase | Klaar | 30 recepten in JSON, zoeken op seizoen/categorie/tags |
| Menuplanner | Klaar | Weekmenu met variatie, seizoenslogica en geschiedenis |
| Boodschappenlijst | Klaar | Aggregatie en optimalisatie van ingrediënten |
| Voorraadbeheer | Klaar | Voorraad bijhouden met slimme restock-suggesties |
| AH-integratie | POC | OAuth2 mobile API voor favorieten en bestellingen |
| Web UI | In ontwikkeling | FastAPI + HTMX + Tailwind CSS frontend |
uv sync # Installeer dependencies
uv run pytest # Run tests (440 unit tests)
uv run pytest -m e2e # Run E2E tests (Playwright)
uv run ruff check . # Lint
uv run ruff format . # Format
uv run uvicorn boodschappenagent.web.app:create_app --factory --reload # Start dev serverVereist Python 3.14+.
src/boodschappenagent/
models/ # Recipe, Ingredient, enums (Categorie, Basis, Seizoen)
repository/ # RecipeRepository (JSON), RecipeSearch (fluent filtering)
planner/ # MenuPlanner, MenuHistory, DagInput/DagPlanning/WeekMenu
utils/ # PortionCalculator
ah/ # AHClient, AHTokenManager (OAuth2 mobile API)
digitizer/ # PDF-naar-recept extractie via Claude Vision
cli/ # CLI tooling (menu, voorraad, digitize)
web/ # FastAPI app, Jinja2 templates, HTMX + Tailwind
data/recipes/ # 30 recepten in 4 categorieen (gevogelte, vis, vlees, vegetarisch)
tests/ # 440 unit tests, TDD
web/ # FastAPI route tests (TestClient)
e2e/ # Playwright E2E tests (live server, iPhone 13 emulatie)
docs/ # Ontwerpdocumentatie
30 gedigitaliseerde recepten als JSON, verdeeld over categorieen:
- Categorie (proteïnebron): vlees, gevogelte, vis, vegetarisch, veganistisch
- Basis (koolhydraat): pasta, rijst, aardappel, brood, geen
- Seizoen: lente, zomer, herfst, winter, alle
from boodschappenagent.repository import RecipeRepository, RecipeSearch
recipes = RecipeRepository("data/recipes").load_all()
winter_vis = (RecipeSearch(recipes)
.filter_by_seizoen(Seizoen.WINTER)
.filter_by_categorie(Categorie.VIS)
.results)Automatische weekmenuplanning met:
- Seizoensfiltering
- Variatieconstraints (geen opeenvolgende zelfde categorie of basis)
- Progressieve constraint-relaxatie bij beperkte receptenpool
- Geschiedenischeck (recent gegeten recepten vermijden)
- Deterministische modus voor tests via
random_seed
from boodschappenagent.planner import MenuPlanner, MenuHistory, DagInput
from boodschappenagent.models import Seizoen
history = MenuHistory("data/history.json")
planner = MenuPlanner(recipes, history)
week = [DagInput(dag=i, personen=2) for i in range(7)]
week[3] = DagInput(dag=3, personen=0) # donderdag niet thuis
menu = planner.plan_week(week, Seizoen.WINTER, "2026-02-09")
for dag in menu.dagen:
if dag.recept:
print(f"Dag {dag.dag}: {dag.recept.naam} ({dag.personen}p)")
# Recept vervangen met respect voor buren
menu = planner.vervang_recept(menu, dag=1, seizoen=Seizoen.WINTER)
# Opslaan in geschiedenis
history.add_week(menu)OAuth2 mobile API (api.ah.nl) voor favorieten en producten. Tokens worden per worktree opgeslagen in data/ah_tokens.json (staat in .gitignore).
Eenmalige login:
- Open deze URL in je browser:
https://login.ah.nl/secure/oauth/authorize?client_id=appie&redirect_uri=appie://login-exit&response_type=code - Log in met je AH-account. De browser probeert daarna te redirecten naar
appie://login-exit?code=XXXX— dat mislukt, maar decodestaat in de adresbalk. - Wissel de code in:
python -c "from boodschappenagent.ah.auth import AHTokenManager; AHTokenManager().login('JOUW_CODE_HIER')"
Daarna werkt bestel automatisch en worden tokens ververst als ze verlopen.
from boodschappenagent import AHClient, AHTokenManager
token_manager = AHTokenManager() # laadt tokens uit data/ah_tokens.json
client = AHClient(token_manager)
lists = client.get_lists()
results = client.search_products("spaghetti")Server-side rendered frontend met FastAPI, HTMX en Tailwind CSS. Geen SPA — HTMX vervangt HTML-fragmenten bij interacties.
uv run uvicorn boodschappenagent.web.app:create_app --factory --reload
# Open http://127.0.0.1:8000/weekStatus: Fase 0 (project setup) afgerond. Base layout met Tailwind, HTMX, AH-kleurenpalet en tab-bar navigatie. Zie docs/implementatieplan-ui.md voor de volledige fasering.
Schaalt recepten naar gewenst aantal porties met slimme afronding per eenheid.
from boodschappenagent.utils import PortionCalculator
scaled = PortionCalculator.scale_recipe(recipe, porties=3)De volledige workflow van menu plannen tot bestellen bij AH:
# 1. Weekmenu genereren (seizoen wordt automatisch gedetecteerd)
uv run python -m boodschappenagent.cli.menu plan
# 2. Menu bekijken
uv run python -m boodschappenagent.cli.menu toon
# 3. Recept vervangen (bijv. dinsdag)
uv run python -m boodschappenagent.cli.menu vervang di
# 4. Boodschappenlijst genereren
uv run python -m boodschappenagent.cli.menu boodschappen
# 5. Bestellen bij Albert Heijn
uv run python -m boodschappenagent.cli.menu bestel
# 6. Menu accepteren (opslaan in geschiedenis)
uv run python -m boodschappenagent.cli.menu accepteerOpties bij plan:
| Optie | Beschrijving | Voorbeeld |
|---|---|---|
-p, --personen |
Standaard personen per dag (default: 2) | -p 4 |
-v, --vrij |
Vrije dagen (komma-gescheiden) | --vrij za,zo |
-d, --dagen |
Per-dag personen (dag:aantal) | --dagen ma:4,vr:3 |
-s, --seizoen |
Seizoen override (auto-detect) | --seizoen winter |
-w, --week |
Week startdatum | --week 2026-03-02 |
Opties bij vervang:
| Optie | Beschrijving | Voorbeeld |
|---|---|---|
-p, --personen |
Wijzig aantal personen | vervang di -p 4 |
-v, --vrij |
Markeer dag als vrij | vervang do --vrij |
-s, --seizoen |
Seizoen override | vervang di -s zomer |
Opties bij bestel:
| Optie | Beschrijving | Voorbeeld |
|---|---|---|
-f, --filter-voorraad |
Filter items op voorraad | bestel -f |
-n, --naam |
Naam voor de AH lijst | bestel -n "Week 10" |
-r, --ref |
AH referentielijst ID | bestel --ref <list_id> |
Beheer je voorraad om boodschappenlijsten te optimaliseren:
# Voorraad initialiseren met standaard items
uv run python -m boodschappenagent.cli.voorraad init
# Voorraad bekijken
uv run python -m boodschappenagent.cli.voorraad toon
# Item markeren als op voorraad of leeg
uv run python -m boodschappenagent.cli.voorraad set pasta --op
uv run python -m boodschappenagent.cli.voorraad set melk --leeg
# Interactieve wekelijkse voorraadcheck
uv run python -m boodschappenagent.cli.voorraad check
# Synchroniseer voorraad met receptendatabase (ontdek nieuwe items)
uv run python -m boodschappenagent.cli.voorraad syncTDD (red-green-refactor) is verplicht. Code quality via ruff.
uv run pytest -v # Verbose tests
uv run pytest --cov # Coverage rapport
uv run pytest tests/test_menu_planner.py # Specifiek testbestand
uv run ruff check --fix . # Auto-fix lint issuesE2E tests draaien een live FastAPI-server met testdata en emuleren een iPhone 13 (390x844).
uv run playwright install # Eenmalig: installeer browsers
uv run pytest -m e2e # Run E2E tests (headless)
uv run pytest -m e2e --headed # Run E2E tests met zichtbare browserTests zijn gemarkeerd met @pytest.mark.e2e en staan in tests/e2e/.