Fig. 1 / 6

Popote

One week of meals for two diets, ending in a full Migros basket

Popote plans a week of lunches and dinners for a vegetarian and an omnivore, with a recipe and macros per person, then fills the Migros Online basket from the list.

  • 8 household scenarios in the planner’s baseline eval suite
  • 3 interchangeable AI providers behind one gateway
  • 13 different dishes in the demo week, Thursday to Sunday

Figures read from the repositories on 24 Oct 2026.

Platform
Web app · PWA
Status
Live, in beta
For
Households of two with different diets who shop at Migros
Year
2026
Role
Product and design direction. Built with Claude Code agents.
Stack
Next.js 16, React 19, TypeScript, Postgres 17, Drizzle ORM, pg-boss, Vercel AI SDK, Playwright
Typeface
Archivo
Commits
1,729 · 1,498 co-authored by agents · read 24 Oct 2026
See it
Landing page
Colour bar sampled from the film: #f5f5f0, #161616, #4ba5e1, #372387, #e12d9b, #f57305.

The film · 0:30

Cyan panel for Alice, magenta for Bob, and a violet strip between them where the two inks overprint as A+B.
Play with sound · 0:30 · 3.8 MB

Everything in this film is also described in the text and the shot list on this page.

Shot list: every frame, described
Frame Time Shot On screen English
Frame 01 0:00 Huge black type on paper reads "on mange quoi" with an orange cursor still typing the last word. « on mange quoi “what's for dinner
Frame 02 0:02 The same question, struck through with black bars, under the heading "Fini le". Fini le « on mange quoi ce soir ? » No more “what's for dinner tonight?”
Frame 03 0:04 Cyan panel for Alice, magenta for Bob, and a violet strip between them where the two inks overprint as A+B. Alice végétarienne, A+B 3 soirs à deux, Bob omnivore Alice vegetarian, A+B 3 evenings for two, Bob omnivore
Frame 04 0:06 Eight bars, cyan left and magenta right, slide in with a violet overlap that widens down the stack.
Frame 05 0:08 A Thursday to Sunday meal grid, cyan and magenta cells with violet for shared dinners, beside a huge black 13. Chaque semaine, de nouveaux plats. 13 plats différents, de jeudi à dimanche Every week, new dishes. 13 different dishes, from Thursday to Sunday
Frame 06 0:10 A full-screen halftone of overlapping cyan, magenta and violet dots with small white stars between them.
Frame 07 0:12 White on black, a giant 0 with a rule and a caption, the first of three figures. 0 idée à chercher le soir 0 ideas to look up in the evening
Frame 08 0:14 White on black, a giant "10 min" above a rule, the second of three figures. 10 min pour valider ta semaine 10 min to approve your week
Frame 09 0:16 The same "10 min" figure held on black, scaled up slightly from the previous frame. 10 min pour valider ta semaine 10 min to approve your week
Frame 10 0:18 White on black, a giant "1 h 30" above a rule, the third of three figures. 1 h 30 de liste et de courses en moins 1 h 30 less spent on lists and shopping
Frame 11 0:20 A black bar slides off the top to reveal paper, a heading, an empty shopping list at 0 of 41 and a thin progress rule. Un bouton, et le panier Migros se remplit. One button, and the Migros basket fills up.
Frame 12 0:22 A product list ticks off item by item as an orange button is clicked and an orange Popote cart waits on the right. Un bouton, et le panier Migros se remplit. Remplir le panier Migros One button, and the Migros basket fills up. Fill the Migros basket
Frame 13 0:24 The orange Popote cart, with a lid on top, rolls along a line that turns orange behind it.
Frame 14 0:26 The Popote logo, cart and wordmark in black, with the tagline beneath and the web address still typing in. Popote. Mange mieux. Pense moins aux courses. Popote. Eat better. Think less about shopping.
Frame 15 0:28 End card with the logo, tagline, the address popote.borden.ch underlined in orange and a line of fine print. Popote. Mange mieux. Pense moins aux courses. popote.borden.ch Popote. Eat better. Think less about shopping. popote.borden.ch

The sheet · 15 frames, one every 2 s

The problem

Two people, two diets, one kitchen and one grocery order. One eater is vegetarian, the other omnivorous, each with their own macro targets and their own habits. Most meals are eaten alone, a few at the weekend are shared, and cooking happens in batches on Sunday.

Planning that by hand means juggling the diets, the week’s Migros promotions and whatever is already in the cupboard, then typing the basket in line by line.

The product

Popote plans one week of lunches and dinners for a household of two. Every meal has a recipe and per-person macros (kcal, protein, fat, carbs). Meals are grouped into cook sessions, so a few Sunday batches feed several days.

Shared dinners are split meals: one common base, animal protein for one plate, plant protein for the other. Each slot is shared or solo, chosen per slot.

Changes are made by saying them, by text or voice: « change Thursday dinner to something faster ». The app shows a diff, then re-totals the day, the week, the list and the basket in one pass.

The shopping list is matched to real Migros products, prices and promotions, and added to the Migros Online basket. Checkout, pickup slot and payment stay with the user. The interface is in French.

How it’s made

Popote is a Next.js App Router application in TypeScript on Postgres, with Drizzle migrations and pg-boss for background jobs. It runs in Docker, self-hosted on a Coolify instance, and installs as a PWA with push notifications and an offline page.

The language model sits behind a gateway with Anthropic, DeepSeek and OpenAI providers, switchable from a settings page, with a soft monthly budget and a cost panel. Speech-to-text and read-aloud in cook mode have their own ports. The pure domain code lives in src/core, and the linter fails the build if it imports from the rest of the app.

The Migros side is an adapter over unofficial endpoints. A fake adapter and a scripted fake model drive the tests, so the main paths run offline. Popote is independent and not affiliated with Migros.

The product was built with Claude Code agents working from GitHub issues, each in its own git worktree, merged only when CI is green.

Details

The visual direction, Surimpression, comes from Zurich-school posters and process-ink printing: paper, a key black, two person inks, their violet overprint, and one spot orange taken from the logo. Square corners, hairline rules, no shadows, no gradients. Archivo is used on its width axis, condensed for data and normal for reading.

The logo is a cloche over a shopping cart with a lightning bolt. It is animated as a glyph: it simmers while a week is composed, drops its lid when ready, and drives along a road on the landing page as you scroll. A motion gate in the test suite rejects raw durations and animated layout properties.

The 30-second film is built only from this system, on 128 BPM bars. The names in it are invented for the example.

Decisions

  1. Fig. 1.1

    Overprint, as a rule

    Cyan is one eater, magenta the other, and a shared meal is where the two inks overprint into violet. Turning a slot shared slides the blocks together.

  2. Fig. 1.2

    A planner with a constitution

    Restrictions and dislikes are absolute, then macro targets, cooking effort, pantry, promotions. The order is written down and the planner follows it.

  3. Fig. 1.3

    Degrades gracefully

    The Migros integration is unofficial and can break. When it or the model is down, the week, recipes and list already made stay usable, offline included.

  4. Fig. 1.4

    A film held to accessibility

    The 30 s film is built from the product’s own design system and checked frame by frame against the WCAG flash thresholds and a reading-speed rule.

  5. Fig. 1.5

    Tested like a product

    485 test files, Postgres integration suites, Playwright on Chromium and WebKit with and without JavaScript, axe on every screen, and 110 visual goldens.

From the app

The Migros Online basket on a phone, with its first three products and 4.05 francs so far.
Fig. 1.6 The basket fills itself. Screen capture from the live app.

Production notes

Commits on the default branch, read 24 Oct 2026
Span 20 Sep to 22 Oct 2026, 33 days
Commits 1,729
Co-authored by Claude Code agents 1,498
Share 87%
Read on 24 Oct 2026

Credits

Product and final cut
Sven Borden
Built with
Claude Code agents · 1,498 of 1,729 commits co‑authored, read 24 Oct 2026
Film
Made in code from Popote’s design system
Printed by
Coolify on a Synology in Vaud

Next print · Fig. 2 / 6

Anatomie UNIL

Film

0:00 / 0:00