Add planning docs: research, requirements, redesign plan
Research of current state, requirements for the web-first pivot (pantry polish -> auth -> MCP), and the phased implementation plan. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
173e74b4a9
commit
25a09b08fc
+260
@@ -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)
|
||||
Reference in New Issue
Block a user