A Wine App
A personal sommelier that lives on the phone, not in the cloud.
A wine app for iOS and Android that inverts the usual architecture: the intelligence — taste profiling, recommendations, scanning a restaurant wine list and picking the bottle — runs on-device. The backend stays deliberately thin: it syncs user state and ships a static catalog, and the heavy lifting (scraping shops, enriching data) happens in batch on local hardware. The interesting bet: modern phones are smart enough that the cloud-brain + dumb-client split is optional.
- Duplicate wine pages merged from 790 down to 57
- One saved-wine record across cellar, wishlist and scans
- Scan refuses to guess between wine editions
- Bottle image pipeline repaired, cutouts and catalog
- Cloud SQL replaced by local Postgres in Docker
- DESIGN.md rewritten from the handoff prototype
- Database moves from SQLite to Postgres on Cloud SQL
- Hidden-gem engine driven by YAML config
- The cache told me the fix hadn't worked
I stripped the camera metadata out of 373 stored images and rewrote each one in place. Then I checked the result: 194 still had it. They…
- Missing data scored zero, so the ranking measured our own pipeline
A tester wrote that picking a food didn't change the wine. The unit tests passed — they score a hand-built wine that is obviously right…
- The engine had already decided — the screen ignored it
Pulled on the scan flow in A Wine App — the part where you photograph a restaurant list and it ranks the bottles for your taste. Found…
- Your cellar count is the hero, not a stat
The redesigned Cellar card in A Wine App makes one quiet bet: the size of your collection is the design. The bottle count is set as a…
- The Pulse: one tile that tells you what the app knows about you
The new fourth card in A Wine App, the Pulse, folds the learning loop into one adaptive tile. It shows one read of your palate: a…
- I cut the wine app's home from eleven surfaces to four
Decision. A Wine App's home screen was an eleven-surface feed — sommelier picks, deals, hidden gems, a weekly card, a quick-action rail,…
- Free models first, paid model last — as a pipeline law
Decision. Catalog enrichment is a strict cascade, and each phase may only fill the NULLs the previous one left: inherit from the producer's…
- Ask the model twice; ship only what it agrees with itself on
I batch-enrich a 100k+ bottling wine catalog with Claude Sonnet — style scores, identity backfill, storage potential. The safety mechanism…
- Decision: the heavy AI jobs live on a Mac Mini, not in the cloud
Decision. For my wine app, all heavy batch work — ingesting catalog data from a dozen shops, deduplicating a 100k+ bottling catalog (a full…
- NULL beats a plausible guess
What I learned. When an AI-extracted field can't be grounded in the source text, NULL beats a plausible guess. Where it bit me: the batch…
- On-device AI is free per call — that's the trap
What I learned. On-device LLM calls cost $0 per call — so nothing in my stack ever flagged that I was making way too many of them. Why it…