The FuelTheFam case study
FuelTheFam is our own product: a nutrition dashboard for sports families, built with Claude Code by the two of us, neither of whom writes code by hand. This page is the case study: how the build applies what The Builder’s Stack teaches, layer by layer and call by call, and where it still falls short.
The product, in one round trip
A parent photographs a plate, and about ten seconds later the meal is logged with its macros. A week of those logs becomes a per-member gap analysis, and the gaps become one grocery list for the household. Everything else on this page sits somewhere on that path.
The photo itself is never stored: it is compressed on the phone, parsed once on the server, and discarded, so only the structured rows survive. The most sensitive data store this product could have had simply does not exist, and the storage layer is where apps like this usually leak.
What runs where
The build is two addresses and five rented services, and since the July replatform both addresses run on Cloudflare: the app moved off Vercel, the marketing page off GitHub Pages. They remain two separate deployments, plain files on one and every secret on the other, so nothing private sits anywhere near the public page, which is the first thing The Software Map teaches you to check.
A static page at fuelthefam.com with a click-through demo on sample data, served as plain files by its own Worker. Nothing private ever touches it.
The Next.js app at app.fuelthefam.com, on Workers through the OpenNext adapter since the July replatform. Every model call runs in a server route here, never in the browser.
Auth plus Postgres. Row-level security is on for all four tables, so the database enforces family boundaries on every query made with a user's own session.
Four calls: parse a typed meal, parse a photo, analyze the week, write the grocery list. The key lives only on the server.
The public nutrition database behind manual food search. The app reaches it through a server route that requires a signed-in user, and the key never leaves the server.
The platform records the app's uncaught errors with readable stack traces, a job Sentry held until the replatform, and Resend sends password resets and signup notifications.
The move to Cloudflare ran as research before it ran as a migration; the field note Why Our Migrations Start as Research Briefs tells that story, including the brief that came back with no.
The model layer: four calls, two tiers
The division of labor is strict. The app’s code does all the arithmetic, from daily totals and weekly averages to each member’s targets, which come from a standard formula. The model handles recognition and suggestions: identifying the food in a photo, estimating the portion, naming the week’s gaps, and proposing what to buy. Each call states a role, its boundaries, and the exact JSON it must return, which is the pattern Get output you can build on teaches.
| The call | Runs | Model | What comes back | The guard around it |
|---|---|---|---|---|
| Parse a typed meal | Every log | Haiku 4.5 | Foods, portions, and macros as fixed JSON | Preview screen before anything saves |
| Parse a meal photo | Every log | Haiku 4.5 | Same JSON, from the image | Compressed upload, size cap, same preview |
| Weekly gap analysis | On demand | Sonnet 5 | Top three gaps with meal suggestions | Language rules; results cached for an hour |
| Grocery list | After analysis | Haiku 4.5 | A categorized list with reasons and swaps | Budget and kid-friendly guidance in the prompt |
How the models actually got chosen
We felt least equipped for this decision, and the repository shows what actually happened: we started on a default, corrected it twice, and upgraded once.
Every call launches on Sonnet, the safe default when nobody tells you how to choose.
An architecture review moves both parse calls to Haiku: structured extraction never needed the big model.
The grocery call hits Vercel's 60-second ceiling on Sonnet and moves to Haiku for speed.
A tune-up ahead of the replatform moves the weekly analysis to Sonnet 5, while Haiku keeps everything that runs often.
Two forces drew the split between tiers: whether the task needed judgment or extraction, and a platform timeout. The July change moved the judgment call up a model generation without touching that split. Neither force appears on a benchmark chart, which is why Choose the model you ship has you run your own inputs through two tiers and keep the cheapest one that clears your bar.
The boundary work: nutrition, minors, and liability
A nutrition product for families is health-adjacent software with children in the data, which puts it closer to high-stakes territory than its cheerful dashboard suggests. The protections landed in two waves: the eating-disorder safeguards on day 3 of the build, and a liability sweep after a pilot user asked, correctly, where the disclaimer was. The protection now has three layers, ordered strongest to weakest.
Under-18 profiles are never offered a weight-loss goal. Members under 16 see coverage words, “Good, Getting there, Needs attention,” instead of calorie numbers. The interface cannot present what the team decided a child should not see.
The disclaimers on signup, login, and the insights page are sentences the team wrote once and owns, including the single referral: if you have concerns about a family member's relationship with food, talk to a registered dietitian or provider.
The analysis prompt bans clinical vocabulary, defines severity as distance from target rather than medical concern, and forbids the model from making referrals, so the one sensitive sentence stays human-owned.
That third layer carries a caveat: the language rules live only in the prompt. Nothing checks a reply for clinical terms before it renders, so if a reply breaks the rules, nothing catches it. The table below counts that.
What $40 a month buys
Four habits hold the bill near the cost of a family dinner: the expensive model runs only on the rare judgment call, analysis results are cached for an hour and reused until new logs arrive, photos are compressed on the phone before they travel, and an 800-token ceiling keeps every parse reply short. The machinery for charging money exists too, with a 10-log monthly meter, plan gates on the expensive features, and an upgrade page, and all of it sits behind a flag that is still off. The beta exists to find out what the product is worth before we design the price.
Instrument by instrument: what is in place and what is missing
The first review happened mid-build: on March 6 we asked Claude to review the codebase Claude had written, and the findings became the auth middleware, the masked errors, the size caps, and the cache. That is the review loop from Review what the AI built. The table below is the fuller version: it holds every instrument the curriculum hands you against this product as it runs today.
Every decision exists, spread across 85 commits and eight pull requests. No single page records the model, the caps, and the call made from real use.
Each prompt states a role, boundaries, and an exact JSON schema, and parsing is wrapped against failure. Nothing range-checks the values before they save.
There are no tests of any kind. Macro estimates from photos have never been scored against a known plate, so accuracy is unmeasured and users are the test suite.
Every AI log passes a preview the parent edits and confirms, children's screens replace calorie numbers with plain words, and the severity language stays everyday.
Row-level security is on for all four tables, every key lives on the server, errors are masked, and the one client that can bypass row-level security runs only after the server verifies who is signed in. The hardening pass after the July replatform closed the rest: an open proxy in front of the food database, an authorization gap in seven server components, a header-injection path in the signup email, secrets that failed silently, and a webhook that failed open. Each fix records its reasoning in the pull request that made it.
Manual food search is grounded in the USDA database, and daily targets are computed in code from a standard formula. AI-parsed macros are estimates with no reference check behind them.
We know the monthly bill, about $40, but not the cost of a single task. A 10-log free meter is built and wired, and the flag that enforces it is off while the price remains undecided.
Error tracking moved from Sentry to Cloudflare's built-in version when Sentry's bundle weight collided with the free plan's size limit; every signup still sends a notification, and the migration left the first written runbook, covering the cutover and its rollback. There is still no runbook for a bad day in production and no gate on changes, because there are no evals to gate with.
One instrument scored not applicable rather than passing or failing: agentic controls. The product’s only write is the user’s own meal log, confirmed on a preview screen; nothing here acts beyond the household, so there is no autonomy to bound yet.
What surprised us
Each of these cost us real time, and each now maps to a part of the curriculum built to save you that time.
“A pilot user asked where our disclaimer was. He was right.”
One piece of feedback triggered the liability sweep: notices on signup and login, a terms page, and an audit of every prompt's language.
“Choosing the model was the decision we felt least equipped for.”
We launched everything on the big model and worked our way down by trial, review, and one platform timeout.
“Our unit economics started as a guess.”
The meter and the plan gates got built early, and the flag that turns them on stays off until we have a price we can defend.
“We asked Claude to research patents and copyright before we shipped.”
Neither of us could judge infringement risk alone, so the legal pre-flight ran as a research conversation first.
“The interface decisions leaned on human factors more than anything technical.”
The preview step, the coverage words for kids, and the ten-second logging target all came from designing for the parent at the kitchen counter.
What we would fix next
One item is gone from this list since the page first carried it: alongside the July replatform, the USDA key left the browser for the server, and a sign-in check now sits in front of the route that spends it. The rest still stands.
- A golden set of thirty plates. Photograph meals with known macros and score the parser against them, so accuracy becomes a number and every model or prompt change reruns the set.
- An output check for clinical terms. The language rules live in the prompt; a small code check on the reply would make the boundary hold even when a reply goes wrong.
- A per-task cost line, then a price. The monthly bill tells us little about what one logged meal or one analysis costs. Those two numbers are what turn the pricing flag on with a price we can defend.
- The one-page Build Plan. The decisions all exist in the history; they belong on a page we can put in front of anyone.
What this case shows
- Two people who do not write code by hand shipped a working AI product in 16 days for about $40 a month.
- Every hard moment in the build was a decision rather than a coding problem: choosing the model, drawing the boundaries, setting the price, judging the legal risk.
- The strongest protections are the structural ones the interface cannot violate; the weakest live in the prompt.
- Holding the build against the curriculum’s instruments found real gaps, and the largest one is measurement: nothing scores the AI’s accuracy yet.
- Every gap maps to a chapter that closes it, and one is closed already: the USDA key placement the audit flagged was fixed in July.
Facts on this page were verified against the FuelTheFam repository and the live product on July 26, 2026, and against the month’s bills on July 23, 2026. Model names and costs go stale quickly, so lean on the decisions rather than the numbers.