Dispensa: home expiry dates, barcode scanning and a shared shopping list, even offline

A pantry app for a family or a shared home: scan the barcode, pick the expiry date with one tap, and the pantry and shopping list are the same on everyone's phone, even offline. What runs out goes on the list by itself, and a reminder of what expires arrives the evening before.

**Dispensa** (Italian for "pantry") is the app a household uses to know what it has, what is expiring and what is missing. Everyone opens it on their phone or computer, in the browser; on the iPhone it goes on the Home Screen and works like an app. It's a personal project for the homes I invite, and from here you can try it without an account in a made-up home, Casa Ginestra, with the pantry already full.

**What it does**

- **Barcodes with the camera.** In the browser the BarcodeDetector API reads them where available, otherwise ZXing-C++ compiled to WebAssembly, which is the route for Safari on the iPhone. If a code can't be read, the product is typed in, with suggestions from the home and the catalogue. - **Name and photo from Open Food Facts**, the open food products database, with the attribution its licence asks for. - **The expiry date in one tap**, with suggested days for each product and the difference between "use by" and "best before". - **The shared shopping list**, in real time and even with no signal in the supermarket. What runs out goes on it by itself. - **The reminder the evening before**, a push notification at the time the household chooses; on the iPhone it arrives with Dispensa on the Home Screen. - **Homes by invitation**: whoever manages one gives a code that lasts 48 hours and works once, and without an invitation there's no sign-up.

**The hard part: two phones with no network.** If two people eat the last yogurt while offline, the pantry must not lose anything. Quantities are never overwritten: every action is a movement, and movements add up in whatever order they reach the server. Everything else merges with rules written once, the same on the phone and on the server; the only choice the app asks people to make is between two different expiry dates for the same package.

**The other: Open Food Facts' limits.** Phones never call it: they ask the server, which keeps a cache shared by every home, reads at most 12 products a minute through a queue, and meanwhile lets the product be saved, so it gets its name as soon as possible.

**What's missing.** The Android app, with Capacitor and Google's scanner, is in the code but not distributed yet. "Cosa cucino?" (what shall I cook?) matches recipes on the phone with what is about to expire, even offline, but the recipe book, which I write from the admin panel, is still empty.

Vue 3 and TypeScript, Fastify and PostgreSQL, in Docker on my server: the app and the database stay under 250 MB of memory and use about 120 at rest. Every change goes through 336 automated tests.

Design, full-stack development and deployment · 2026

Vue.js, Fastify, PostgreSQL, IndexedDB

View the site

Andrea Coppetta