// op_015 — case study Live

Oh! You Fancy Focaccia

Oh! You Fancy Focaccia home page screenshot
An artisan bakery selling out of a farmers market stall two mornings a week, taking custom orders through direct messages. Thirty-three bakes, a menu that turns over with the season, and no way for a customer to see what is available or place an order without a conversation — while the baker had no record of what had been promised, at what price, for which market day.
One Catalog, Three Readers
The thirty-three bakes live in a single JSON file read by the page generator, the database seed and the test suite. The first version kept the menu in three places and they drifted — of thirty-one bakes on the gallery, only two could actually be ordered. Anything that still names a bake by hand fails the build rather than shipping a name the order page has never heard of.
Static Front, No Build Step
The customer-facing pages are generated from one design source into plain HTML, CSS and per-page scripts. Nothing is compiled at request time and no script is inline, which is what lets the site ship a Content-Security-Policy with no unsafe-inline.
Dates the Server Decides
A requested date is validated server-side against the market days, a configurable minimum-notice window and the baker's own vacation blocks in Postgres. The calendar on the page is a convenience; it is never the thing that decides whether an order can be taken.
Prices That Stay Put
Order lines snapshot the unit price at the moment of purchase. Repricing the menu, renaming a bake, or taking one off the board never rewrites an order already placed — past orders keep the item and the price they referenced.
Migrations Without Tooling
Schema changes are add-if-missing, and data corrections are one-shot behind a marker row, so a fresh database and a year-old one boot identically with nothing to run by hand. Each correction matches only the value it is replacing — a photo, price or description the owner has edited herself is never overwritten on restart.
Email as the Interface
Resend carries the thank-you, the confirmation and payment receipts, with a tokenised respond link so the baker can accept or decline from her inbox. Without an API key nothing goes out and nothing fails: orders still save, because a bakery whose email is not set up yet should not be a bakery that cannot take orders.
The Owner's App
An Expo companion app talks to the same Express and Postgres server and shows the same order book — accept an order at the market table without opening a laptop, and hear about a new one the moment it lands. Customers order from the website; nothing in the app is for them.
Deployment
Railway with managed Postgres, Cloudflare in front. 102 tests run in CI against a real Postgres service rather than a mock, because the parts worth testing here are the date logic, the price snapshots and the migrations.
Every bake on the board can be ordered, priced, and photographed from one list the owner controls, and she runs the whole pipeline from her inbox or her phone. The single-catalog rule is the part that keeps paying: a rename now reaches the gallery, the bill of fare, the order form and the tests in one commit, or it stops the build — which is how a menu of thirty-three bakes stays truthful without anyone proofreading four pages.