Mobile Home v2 — Design review, pass 9
Tied to 2026-07-30-mobile-home-v2.md. Categories/Vendors/Ingredients filtering lives in Discover,
not Home. Reload for the first-run wizard asking about allergies and ingredients you find undesirable —
skippable, editable later from Profile. Every matching product always shows an exclamation badge naming the
specific ingredient, everywhere it appears. There's no separate "hide conflicts" control anymore — Discover
now behaves exactly like Home and vendor browsing, always showing every match. Checkout still mirrors the real
app's single "Confirm order" sheet from an earlier pass.
Reload for the first-run wizard, or use Profile → Allergies & Preferences once set. Pick something under "I have an allergy to" and you'll see a red ! badge — naming the ingredient — on matching products everywhere, including Discover search results, which are never hidden. Filters (Categories/Vendors/Ingredients) live in Discover, with active ones filled orange and shuffled to the front of the row. Tap a vendor's See all, a category, or any product to drill in. In Cart, tap Checkout to open the confirm sheet. The robot button between Discover and Cart opens the AI Assistant.
The three filter pills used to sit on Home, above the Vendors section, even though nothing on Home was actually filterable by them (Home always shows every vendor/category — that hasn't changed). Discover is the tab that actually does filtered browsing, so the pills — and the sheet they open — moved there. Home goes back to being pure browse: Favourites, Vendors, Categories, nothing else.
An earlier pass added a "Hide items with my allergens or undesired ingredients" checkbox, checked by default, as a visible replacement for an even earlier silent-hiding mechanic. That checkbox itself has now been removed too — there is no hide/show control anywhere in Discover anymore. Every match always appears, exactly as Home and vendor/category browsing already worked; the exclamation badge (naming the specific ingredient) is the only conflict indicator anywhere in the app now, which also makes the app's behavior simpler to describe: nothing is ever filtered by allergy/undesired status, only flagged.
Every conflict surface — the exclamation badge's tooltip, the warning banner on product detail, even the compact badge inline in Discover's search-result rows — now states the specific ingredient(s), e.g. "Contains Milk (allergy) · Wheat (undesired)". A product can match multiple ingredients across both lists at once; all of them are named, not just the first match found.
It names both sections directly rather than making the customer guess what's inside (an alternative, if you want something shorter: "Dietary Preferences"). The first-run wizard is two skippable steps — "Do you have any food allergies?" then "Any ingredients you find undesirable?" — each a chip grid of the same 9 ingredients; picking one in one step removes it from the other, since a single ingredient can't be both a medical allergy and a personal "don't eat" for the same person. Profile's editor reuses the identical chip logic on one page instead of two steps, since editing benefits from seeing both lists at once. Skipping the wizard doesn't force it to reappear — it can be filled in anytime from Profile, where a live summary ("2 allergies · 1 undesired" / "Not set") shows the current state without opening it.
The picker deliberately excludes Gluten-Free and Sugar-Free from both lists. Those two are "free-from" claims a product either has or doesn't (positive labels), not ingredients a person is allergic to or finds undesirable by that name — "I'm allergic to Gluten-Free" doesn't parse. Someone avoiding gluten today has to approximate with "Wheat," a reasonable proxy but not medically precise (gluten also lives in barley/rye, not just wheat). Getting this exactly right would need a genuine "Gluten" flag distinct from the "Wheat" contains-ingredient and matched against the "Gluten-Free" claim — flagging as a real, not-yet-resolved gap in the D6 ingredient taxonomy, not something this mock-up should paper over by inventing new ones unilaterally.
The exclamation badge (top-right of every product thumbnail, offset clear of the favourite heart where both appear) and the matching outline on ingredient chips both follow the same rule: allergy conflicts render in red, undesired-ingredient conflicts in amber, and a product matching both takes the more severe red. This repeats across every surface a product or ingredient appears — Home's vendor sliders, vendor/category/ingredient grids, product detail, cart rows, favourites, Discover's search-result rows, and even the AI Assistant's suggested products — so the warning is never surprising the one time it matters.
This is entirely client-side/in-memory in the mock. A real version needs a new customer-level
preference store (nothing like this exists today — the closest precedent is the
GenericAttributeService pattern already used elsewhere on Vendor, which could
plausibly extend to Customer), a save/read API endpoint, and a decision on whether allergy
data has any extra handling given its safety sensitivity (e.g., should support/ops ever see it, does it
need different retention treatment than an ordinary preference). None of that is resolved here — this
pass is UX and interaction only.
An earlier pass had a manual "Company lunch / Personal order" toggle in Cart, which misrepresented the mechanic — it made it look like the customer chooses an order type. They don't: a company-lunch order is just what you get when the delivery address happens to be one of the company's registered addresses (D3b); everything else is a personal order. That's now modeled correctly — the confirm sheet's address card is the single source of truth, and the warning only appears when the selected address is personal and no vendor is running a Free-Delivery promotion. Tap "Change" on the address card to see both states.
Real mysnacks-mobile checkout is a single bottom sheet titled "Confirm order" — address and delivery time are picked earlier (today, via Home's own pickers) and shown here read-only with a "Change" link, next to the item list and a submit button. This mock matches that shape exactly rather than inventing a new checkout pattern: same card layout, same "Change" affordance, same black "Confirm order" button. The one difference from production is what triggers the banner under the cards — real production shows an allowance/self-pay warning there; this mock repurposes that exact slot for the benefit-eligibility banner, since it's the same "surface something important right above the confirm button" pattern.
Changing the address is fully interactive here so the eligibility logic can be demonstrated. "Change" on delivery time just toasts, since Schedule picking isn't part of this redesign. Tapping "Confirm order" clears the cart and shows the real app's own success copy ("✅ Order confirmed") for fidelity — it isn't a proposal to change checkout itself, which stays out of scope for this Home redesign.
The FAB straddles the tab bar (half in, half overflowing into content), centered so it sits between Discover and Cart on this 4-tab bar rather than on top of any one tab. It opens a pushed screen with a scripted opening exchange (a pre-workout, low-carb/high-protein ask → three suggested products with one-tap "+ Add" → an offer to generate a 2-week plan), plus a real text input for follow-up questions and a reset icon to start over. This whole feature has no backend design yet — no macro/nutrition data exists in the label taxonomy, no recommendation endpoint, no plan-persistence concept — it would need its own design pass before going further than this mock.
An earlier pass used a Home-only floating search pill. With a 3-tab bar the AI FAB's center landed exactly on Cart, which read like it belonged to Cart specifically. Adding Discover as a 4th tab fixes that structurally — the bar's center now falls in the gap between two tabs — and gives search a permanent, reachable-from-anywhere home, now also carrying the Categories/Vendors/Ingredients filter pills that used to sit on Home. This is a real reversal of the original D9 decision, worth reflecting in the design doc if this direction sticks.
Ingredients live on each product; a vendor card's ingredient row is the union of its products' ingredients computed at render time — the "derived only" answer locked into D6. A vendor with several different products can get a crowded chip row — a real consequence worth having an opinion on.
Mock-up 9 — removes the "hide conflicts" checkbox entirely; Discover never hides matches, same as Home and vendor browsing. The exclamation badge is the only conflict indicator left in the app.