All projects
WebPre-launch2026

OPEN DOOR BAKERY

An online-only bakery near Glasgow, run by one person. I built the shop customers order from, the dashboard she runs it from, and everything underneath both. The interesting part is what actually limits a bakery, which is not how much you have in stock — it is how much you can get out of one oven on a particular morning. The build is finished and deployed. What is left before it opens is not code.

Client
Open Door Bakery — Hamilton, Scotland
Scope
Customer shop, admin dashboard, everything behind both
Timeline
July to September 2026, evenings and weekends
Stack
Next.js 15, React 19, TypeScript, Neon Postgres, raw SQL, Stripe, Resend, Cloudinary, Vercel
Status
Built, deployed and handed over
Live
opendoorbakery.com — password-locked until opening day

The vision

A bakery she could run from her kitchen, that takes orders while she is asleep and tells her what to bake in the morning. Customers pick a day and a collection slot, or get it delivered locally. Celebration cakes ordered properly in advance rather than argued out over messages. Wholesale orders kept separate from everyone else's. And all of it run by her, on her own, between bakes.

The thing that makes that harder than it sounds is that a bakery does not run out of stock the way a shop does. It runs out of Saturday morning. Twelve products, each needing its own amount of notice, all wanting the same oven and the same pair of hands — and an order only works if the baking fits into the days before the date the customer wants it.

So three things decide whether an order can happen, and they do not agree with each other. Every product needs its own notice, and a basket takes the longest one in it — a croissant ordered alongside a celebration cake waits for the cake. Every collection slot has a number of places, or no limit at all, or none on a day that is closed. And anything can simply be off on a particular day for its own reasons. Getting those three to agree is most of the job, and it is the part a ready-made checkout hands straight back to you.

There was nothing to copy from, either. This is the first system the bakery has had, so every rule in it came out of how she described the work.

What I did

Build it or buy it is worth answering straight: a bit of wanting to and a bit of needing to. Every rule above could be forced onto a ready-made platform with enough add-ons bolted to it, so this was not the only way. What building it bought was rules that behave exactly as described instead of roughly, and a running cost of nothing while the business has no money coming in.

It is one application wearing three faces: eleven pages for customers, twelve for the baker, and the machinery in between. The database is plain SQL with no layer of translation on top, which is a deliberate choice — it is a small system and I would rather read what it is actually doing.

Most of what a shop is, though, is the unglamorous half. A basket you can fill on a phone at eleven at night and still have in the morning. Prices that add up to the same total on the page, in the basket and on the card statement. An order that goes somewhere when you pay for it, gets a reference you can quote, and moves through states the baker can see — placed, paid, baking, ready, collected. A confirmation email. A way to find your order again and cancel it without making an account first, because nobody making one order wants a password. None of that is interesting and all of it has to be right, and it is exactly the half a platform hands you free.

So: money is counted in pence end to end, with the rounding tested, because a total that disagrees with the card statement by a penny is a support email every time. The card details never reach this application — checkout hands over to Stripe and comes back, which is the one part of a shop worth letting somebody else be responsible for. Availability is tracked per product per day rather than as a single stock number, since a bakery does not have twelve of something sitting on a shelf, it has whatever it has time to make that morning. And the places left in a collection slot are counted from the live orders every time rather than kept as a running total, so they cannot drift and cancelling an order genuinely gives the place back to the next person.

The rules that decide whether an order is possible are enforced where they cannot be got around. Capacity is checked again on the server when the order is placed, not taken on trust from the page that offered the slot — anyone can edit what a page sends, and two people can press the button at the same moment. Delivery is worked out from the first half of the postcode rather than a distance on a map, which is fiddlier than it sounds: ML10 is not inside ML1, and the obvious way of checking says it is.

The dashboard is the half that decides whether any of this gets used, because the person using it runs the bakery on her own between bakes and has no patience for software. So it is built around not making her think. Leaving the number of places blank means unlimited rather than nagging her for a number. How healthy a price is shows up as a word rather than a percentage. And if any ingredient in a recipe has no cost against it yet, the product says its cost is unknown instead of showing a confident figure that happens to be wrong.

The decision that kept paying off was making it run on a laptop with nothing set up. No database to install, no accounts, no keys — download it, start it, and it builds and fills its own database. Every outside service quietly writes down what it would have done instead of falling over, and the checkout completes without a payment provider attached. That is what makes it testable, and 136 tests run against it.

The evidence

Even the empty state is the bakery talking. It is also the state everything else depends on: the basket is what carries the longest lead time in it, so it decides the earliest day the whole order can be ready.