Web App · Household

A shared list
that watches the budget.

A self-hosted shopping-list app in the spirit of Bring!, extended with price comparison across Swiss supermarkets and a monthly household budget. Installable as a progressive web app.


The idea

Tap to shop,
not drag and swipe.

The whole household shares one shopping list. Items are added by tapping tiles — the catalogue and the history of past purchases sit as a grid, and a tap moves an item onto the current list. No drag-and-drop, no swiping; the interaction is deliberately simple enough for everyone in the family to use.

Underneath, the app tracks every shopping trip with date, store, and receipt total, and shows how much of the monthly budget is left at any time.


Features

List, budget, prices,
rhythm.

// LIST

Shared list

One list for the household, grouped by category in shopping-aisle order. Past purchases become reusable tiles; a tap brings an item back. AI suggestions for the current list are clearly marked and can be accepted or declined.

Tile selection AI suggestions
// BUDGET

Monthly budget

A fixed monthly budget with a reset. Each trip is recorded with date, store, and receipt total. The remaining amount is calculated live rather than stored, and a widget shows budget, spent, and remaining at a glance.

Live remaining Per-trip record
// PRICES

Price comparison

Per item and per basket across three Swiss supermarkets. Where pack sizes differ, the comparison uses unit price so the result is not misleading. The time of each price lookup is shown, so you know how current it is.

Per basket Unit price
// RHYTHM

Rhythm detection

The app learns how often recurring items are bought — household staples like toilet paper or pet food — and suggests them when they are due again. The detection is deterministic, based on the interval between past purchases.

Recurring items Deterministic

Architecture

Local stack,
local AI.

The app runs as a container stack on local hardware: a web frontend and API, a background worker for price lookups and rhythm calculation, and a PostgreSQL database that is never exposed outside the stack. The language-model work is sent to the local AI servers over an internal API.

Product matching — especially mapping a generic item to a supermarket's own-brand equivalent — is handled by a local language model with user confirmation, after which it is editable. The price comparison and rhythm detection run deterministically in code, not in the model, so the numbers are always reproducible.

Frontend
Installable progressive web app
Backend
Python API + worker
Database
PostgreSQL, stack-internal only
AI
Local LLM for product matching
Roles
Admin and restricted accounts
Deployment
Ansible, HTTPS, login required

Design decisions

Why it works
the way it does.

Tile selection over drag-and-drop, because it is the interaction the whole family can use without friction. No real-time sync between users, by choice — the list refreshes on reload and when a new product is selected, which is enough for a shared household list and avoids a lot of complexity.

The price lookups are the most fragile part: supermarket sites change their structure without warning. Each store has its own independent adapter, so a broken one does not take the others down with it. Roles separate admin functions — setting the budget, managing users, editing product mappings — from the everyday tapping and checking off that everyone can do.