diff options
Diffstat (limited to 'requirements.md')
| -rw-r--r-- | requirements.md | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/requirements.md b/requirements.md new file mode 100644 index 0000000..6c71a97 --- /dev/null +++ b/requirements.md @@ -0,0 +1,260 @@ +# Food App — Requirements (pivot to web-first) + +> Written 2026-06-22, after reviewing `research.md` and interviewing Tom. +> This supersedes the Caine-centric design. Pairs with `research.md` (current +> state) — this doc is the *target*. + +## The pivot, in one line + +Caine (the Matrix LLM assistant) was never really used — it cost too much per +call. **The web UI becomes the primary interface.** An LLM can come back later +as an MCP server riding on the existing claude.ai subscription (no per-call +cost), but that's a later phase, not now. + +## The one constraint that wins + +**Ease of use beats everything.** This is a single-user personal app, low +stakes. When a requirement trades correctness, completeness, or robustness for +less friction, friction wins. Specifically: fewer fields, fewer taps, fewer +decisions, nothing that nags, and updating the pantry should feel like nothing. + +**Mobile-first, not mobile-also.** The pantry is used standing in the kitchen +or at the shop, on a phone — that's the primary device, and it's fiddly today. +Design for a one-handed phone screen first; desktop is the afterthought. +Concretely: big tap targets (state changes and add are thumb-sized, not +table-cell links), no tiny number inputs or cramped rows, single-column +layouts, no horizontal scroll, controls reachable in the lower half of the +screen. If something works on the phone it'll be fine on desktop; the reverse +is what's been failing. + +Everything below is judged against that. + +--- + +## Priorities (Tom, 2026-06-22 — current call) + +In value order: + +1. **Pantry: make it a bit nicer in the web UI.** Not a ground-up rebuild — + incremental polish (the In/Low/Out state + fast add from §2), enough that + keeping it accurate isn't a slog. It needs to be *reasonably* accurate + precisely because of #3. +2. **Add some auth** (§1) — login once, long session. +3. **MCP server with claude.ai — the highest-value piece.** The whole point: + stop hand-reciting "here's what's in my pantry" every time. Claude reads the + pantry directly in cooking mode. Almost certainly also the *lowest-friction + update path* — say "I used the last of the noodles" and Claude writes it + back — which is the real answer to the pantry-is-tedious problem. + +Everything else in this doc (web what-can-i-cook, shopping rethink, web +cook-logging, fixed recipes, §4.1 substitutions) is **deferred** — nice, not +now. Detailed below for when we get there. + +**The synergy that justifies the order:** #3 is *why* #1 only needs to be "a +bit nicer" rather than perfect. If Claude can both read and update the pantry +conversationally, the web UI becomes the glanceable / manual fallback, not the +primary data-entry surface. So don't over-invest in pantry UI — invest in +making the data MCP can serve trustworthy and easy to nudge. + +--- + +## 1. Auth — log in once, then forget it + +Decision: **a simple login page + a very long-lived session** (≈1 year cookie). +Log in once per device; never get prompted again on that device. + +- Standard Django session auth (`login_required`) on all `/app/` views — no + HMAC, no signed requests, no per-request secret. (The HMAC idea was heavier + than needed for one user.) +- Set `SESSION_COOKIE_AGE` long (~1 year) and `SESSION_EXPIRE_AT_BROWSER_CLOSE + = False` so the session survives restarts. +- One user account is enough. `/api/` keeps its existing token auth for the + future MCP client. +- This also lets us drop the `@csrf_exempt` hacks — a logged-in session has a + real CSRF token, so HTMX POSTs can be protected normally. + +Security is explicitly *not* the top priority, but this gives a real baseline +(no more wide-open `/app/`) at near-zero friction. + +## 2. Pantry — the redesign (this is the heart of it) + +Today the pantry is "all just frustrating": adding is slow, quantities drift +out of date the moment you cook, expiry dates are fiddly to set and chase, and +it's a separate chore that's easy to forget. The fix is to **stop tracking the +pantry like a spreadsheet and track it like a fridge you glance into.** + +### 2.1 Track presence, not precise amounts + +Replace exact decimal quantities as the primary signal with a simple state: + +> **In stock · Running low · Out** + +- One tap to change state (e.g. cycle In → Low → Out, or three buttons). +- Quantity becomes *optional metadata* (a free note like "½ bag", "3 left"), + never required, never the thing the app reasons about. +- This kills the "quantities drift after cooking" problem outright — you don't + maintain a number, you flip a flag when you notice. + +> **Open decision:** some items genuinely want a rough count (eggs, noodle +> nests). Proposal: keep the optional quantity note for those, but the matcher +> and shopping logic only ever look at the In/Low/Out state. Confirm before +> building. + +### 2.2 Fast add + +- A single search box: type → autocomplete against known ingredients (and + aliases) → tap to add. Defaults its unit/location from the `Ingredient` + record, state defaults to "In stock". Zero further fields needed. +- If the name isn't known, add it inline in the same flow (it auto-creates the + ingredient, like the API already does). +- **Quick-add chips** for staples and recently-used items — one tap, no typing. +- On mobile this is the make-or-break screen: the search box and chips sit near + the bottom (thumb reach), adding an item is one tap, and the In/Low/Out + control on each row is a proper button, not a fiddly inline link. The current + table-of-tiny-actions layout is exactly what's being replaced. + +### 2.3 Expiry stops nagging + +- Expiry dates become fully optional and de-emphasised. No required date entry. +- Instead of chasing exact dates, a lightweight **"use soon"** flag you can tap + on an item (and an optional date if you actually care for something specific). +- Keep the existing freezer rule (frozen = no expiry). Defrosting (freezer → + fridge) can set a soft "use soon" instead of computing a hard date. + +### 2.4 Updating the pantry as a by-product, not a chore + +The biggest win against "I forget to update it": make other actions update the +pantry for you, so the standalone chore mostly disappears. + +- **Logging a cook** optionally flips the ingredients it used toward Low/Out + (replaces the brittle decimal-deduction logic). +- **Checking off a shopping item** marks that ingredient back to "In stock" in + the pantry — closing the buy → restock loop automatically. + +## 3. Recipes & "what can I cook" — keep it, but make it one implementation + +Decision: **keep meta-recipes and the what-can-i-cook matcher** — it's the part +Tom actually wants. But: + +- There are currently **two separate matchers** (`views.what_can_i_cook` JSON + and `views_htmx.recipes_page` HTML) that have already drifted. Collapse to + **one shared function**; both the page and any API/MCP call use it. (This is + also the "two implementations hanging around" Tom flagged.) +- The matcher moves to **presence-based**: a required slot is satisfied if any + of its options is In (or Low) — no quantity comparison. Simpler, and matches + the new pantry model. +- Servings is currently hardcoded to 2 in the web page; with a presence-based + matcher, servings stops mattering for "can I cook this", so we can just drop + the servings input from that view. +- Fixed `Recipe`s: keep the model, but **de-scope the URL import for now** — it + never links ingredients (see `research.md` §7), so imported recipes are + half-broken. Cooking ideas live in claude.ai cooking mode anyway. Don't + invest here until the MCP phase, if ever. + +## 4. Shopping list — rethink the flow + +Tom was explicitly unhappy with the current flow. Requirements: + +- Generation stays smart (staples that are Out, "use soon" items, gaps for + required recipe slots) but should be **additive and forgiving** — generating + again shouldn't wipe manual additions or duplicate. +- Checking an item off should (a) cross it out and (b) restock it in the pantry + (see §2.4). +- Needs a clear "done shopping" action that tidies the list. +- Keep it dead simple — a phone checkbox list, grouped by aisle/section. + +### 4.1 "Can't find it at the shop" — substitutions (important to Tom) + +A recurring real pain: Tom goes to the shop to buy something and it's not +there, and then he's stuck. He wants help *in the moment* knowing what else +works. + +- **Partial fix available now, no LLM needed:** the meta-recipe slot model + *is* a substitution table — a protein slot already lists pork mince OR + chicken, etc. So a shopping-list item that came from a recipe slot can show + "alternatives that fit the same slot" inline. If you can't find pork mince, + the list shows the other proteins that recipe accepts. +- **Richer substitutions need the LLM/MCP (Phase 2):** general swaps the app + has no data for ("no fresh basil → dried is fine", "no crème fraîche → use + yoghurt") require world knowledge. That's a claude.ai-via-MCP job: it reads + the shopping item + recipe context and suggests a real-world substitute. +- So: ship slot-based alternatives in the web UI now; treat "smart, open-ended + substitution at the shop" as a headline use case for the MCP phase. + +## 5. Cook log — make it usable from the web + +- Add a **web UI way to log a cook** (currently API/admin only): pick a + meta-recipe, tap the slot choices you used, optional rating + note, save. +- `log-cook` must accept and store `rating` (the model field exists; the + endpoint ignores it today). +- Route cook-logging through model validation so the "exactly one recipe link" + rule is actually enforced (today's `log_cook` bypasses `clean()`). + +## 6. Cleanup / housekeeping (do first) + +- **Run `/simplify` first**, before feature work, to clear the obvious cruft + (duplicate matcher, dead `filterset_fields`/`search_fields` with no + django-filter installed, the freezer-first deduction bug if deduction + survives the redesign). +- Production baseline: `DEBUG = False`, real `SECRET_KEY` from env. Low + priority but cheap. + +## 7. Later — MCP (Phase 2, optional) + +Once the web UI is solid, wrap the existing API in an **MCP server** so +claude.ai "cooking mode" can read the pantry and (maybe) log cooks. This is the +integration Tom actually wanted from Caine, without the per-call cost. Explicit +non-goal for now — listed so the API stays MCP-friendly in the meantime. + +Two things this phase unlocks (and why it's worth keeping the API clean): + +- **Cooking blocks still work.** MCP only *feeds data into* the claude.ai + conversation — it gives Claude tools to read the pantry. It does not change + how claude.ai renders cooking mode. So Claude pulling ingredients from the + food app and Claude producing its nice formatted cooking blocks are + independent: you get the blocks *and* they're grounded in your actual pantry. +- **Smart shop-floor substitutions** (see §4.1) — the open-ended "this isn't on + the shelf, what else works?" question is the main thing MCP buys over the + built-in slot alternatives. + +--- + +## Build order (current) + +1. `/simplify` pass (running) — behavior-preserving cleanup of the existing + code so the next steps build on something tidy. +2. **Pantry polish** — In/Low/Out state + fast add in the web UI (§2). Scoped + to "a bit nicer", not the full redesign. +3. **Auth** — login page + ~1-year session, drop `@csrf_exempt` (§1). Fold the + cheap production baseline (DEBUG off, real SECRET_KEY) in here since we're + touching settings anyway. +4. **MCP server** — the goal. Expose pantry **read and update** to claude.ai + cooking mode, so Claude can both see what's in stock and write changes back. + Reuses the existing `/api/` + token auth. + +Deferred until after the above (still wanted, just not now): web +what-can-i-cook, §4.1 slot-based substitutions, shopping flow rethink, web +cook-logging. + +## Open decisions to confirm before building + +- **Quantity**: drop exact decimals entirely in favour of In/Low/Out + an + optional free-text note? (§2.1) — recommended yes. +- **Fixed recipes**: park the URL-import feature rather than fix it? (§3) — + recommended yes. +- Anything here that's actually *more* friction than today — call it out. + +--- + +## Original notes (Tom, preserved) + ++ interface: never really ended up using caine due to cost issues. was a nice idea though. ++ if we went down the route of llms again, maybe a mcp. could claude.ai connect with it ++ current food flow is using claude.ai and its "cooking mode", issue is that it doesnt integrate with my pantry ++ pantry was tedious to update, not sure the best approach here. might just have to tough it out ++ webui interface was generally clunky ++ security not the highest prio but would be good to have some basic auth ++ lets run the /simplify skill firstly ++ tagging recipes never really worked, feels like theres two implementations of it hanging around ++ auth just scares me, i want the least friction way of doing this. a hmac secret or something might be nice for fe <> be and a simple log in page would be good. although i really dont want to have to log in every time ++ pantry: it's all just frustrating at the moment (adding slow, quantities drift, expiry fiddly, easy to forget) |
