Skip to content
Back to projects

Personal project · Case study

The House Menu

Result

In daily use at home, backed by 133 tested database migrations

Three House Menu phone screens on a dark counter: the calendar feed of guest checks, an open meal ticket, and the grocery list

A phone-first meal-planning app I built for my household. Every meal lands on a calendar as a diner guest check, and the app keeps track of what's in the pantry, what each meal costs, and what goes on one shared grocery list.

ReactVitePWASupabase PostgresVercel FunctionsDockerClaude Code

Personal project, in daily use at home. The repository is private; all screenshots come from the app's built-in demo mode with fictional data.


Overview

Planning meals for a family turns out to be an inventory problem. A pot of rice cooked on Sunday feeds three lunches, a pack of chicken is split across two dinners, and the grocery list should only contain what's actually missing. The House Menu models all of that.

Meals are planned as "arcs" that can span several days. Each meal records who's eating and draws on a pantry kept as a ledger of available and reserved stock. Locking a meal reserves its ingredients and buys only what isn't already covered. The result is a single grocery list with price tracking, installable from the browser as a PWA.

The interface is styled as paper guest checks on a dark diner counter, with its own set of design tokens and about 35 HTML design canvases behind it.

Calendar feed of meals as paper guest checks with times, diner initials and READY stamps

The calendar feed

The calendar feed
An open meal ticket for roast chicken with ratings, prep options, add-ons, nutrition and order cost

An open meal ticket

An open meal ticket
Menu drawer for an empty dinner slot showing full price, discounted cost from stock, and grocery spend

Picking a meal, priced against the pantry

Picking a meal, priced against the pantry
Grouped grocery list with needed quantities, prices, crossed-off lines and an expected total

One shared grocery list

One shared grocery list
Pantry drawer with leftovers, reserved items to verify, a shelf count, and category counts

The pantry ledger

The pantry ledger
Recipe card with ingredients, numbered method and yield

A recipe card

A recipe card

Technical Highlights

Tested migrations
133
Commits
742
To build
~6 wks
Plan documents
~60
  • Ledger logic lives in Postgres. Anything that moves quantities, money, or lock state goes through database functions (RPCs), not client code. Stock is split into available and reserved, and incoming stock is derived on the fly from grocery lines that are committed but not yet received. New meals plan against available plus incoming, which prevents double-buying.
  • Every migration is tested, then sabotaged. A test runner loads the full stack of 133 migrations into a throwaway postgres:16 Docker container and runs each migration's SQL test file. A second "sabotage" pass then deliberately breaks each database object and checks that the expected test blocks fail, and only those. A test that can't catch a real bug counts as a failure.
  • A secret-free demo mode. A build-time alias swaps the Supabase client for an in-memory fake that mirrors the query builder, the RPCs, the derived views, and the triggers. The real client is never bundled, so the demo can't leak credentials, and a check script confirms that locking and unlocking a meal leaves every item's stock unchanged.
  • A narrow write API for an AI assistant. I plan meals by chatting with Claude on my phone, and it writes to the app through one serverless function that allows a short list of actions. The assistant can propose changes, but every quantity goes through the same database functions as the UI, and malformed requests are refused with an explanation of what was expected.
  • Passkey sign-in. Family members enrol through a one-time link that becomes a single-use token, then register a passkey on their own device. The server-side secret lives only in the hosting environment.
  1. Claude chat
  2. Narrow write API
  3. Postgres functions
  4. Pantry ledger
The AI assistant's write path: a short list of allowed actions, then the same database functions the UI uses.

Built with AI, Governed by Rules

The House Menu came together in about six weeks (742 commits) with Claude Code. What kept it coherent is written process: a CLAUDE.md rulebook that states the data model and the principle "deterministic code in the write path", about 60 plan documents that are written before work starts and kept after it closes, and scoped rule files that load only when their part of the codebase is touched.

The database tests exist for the same reason.