i-built-a-booking-app-because-i-was-annoyed.mdx

I built a booking app because I was annoyed

A client's third-party widget kept breaking. I wondered how much of it I could build myself. The answer changed what I thought was possible.

Setup

I’ve helped a few friends in the spa industry with their websites. Part of that work meant embedding third-party booking widgets — the kind that handle scheduling, payments, and confirmations so the business owner doesn’t have to think about it.

One of my clients kept running into payment issues with her provider. Fees that didn’t make sense. Breakage at the worst times. Support that went nowhere. I’d patched around it more than once, and one day I hit a wall and thought: how much of this could I actually build myself?

I wasn’t planning to start a product. I was annoyed on behalf of a client. That’s usually where the real builds start.

What I tried

I started in Cursor, which was my main environment at the time. I was already using Anthropic models almost exclusively — Claude was the one I kept reaching for inside Cursor, so I was essentially paying one company to route me to another.

I made the switch to Claude Code CLI for two reasons: cost and simplicity. Running Claude directly in the terminal cut out the middleman and gave me something that felt more like a real workbench. The terminal had always felt intimidating, but once I was in it, it made sense. You’re just closer to the thing you’re building.

I also stood up a local OpenClaw instance — a personal agent system — and named it JB (Julius Bot). JB became my testing partner. I’d use it to run through user flows, stress-test edge cases, and catch things I’d missed. Having a second agent to interrogate the build was one of the better decisions I made early on.

The stack came together piece by piece: scheduling logic, form handling, confirmation emails, a business owner dashboard. Nothing exotic. Just the things a booking system actually needs to do.

Where it broke

Everywhere, at first. That’s normal. What I wasn’t prepared for was how different “it works in testing” feels from “a real customer is using this right now.”

The moment we onboarded our first real customer, the nature of the problems changed. It stopped being about features and started being about architecture. I realized I hadn’t thought carefully enough about dev vs. prod environments. The database and the code needed proper staging. Changes that seemed small — like how a customer’s name renders in a confirmation email, or how the business owner could edit their own scheduling labels — turned out to touch five things I hadn’t mapped.

The scariest part wasn’t a bug. It was realizing that I was one careless change away from breaking something a real person was depending on. That’s a different kind of pressure than building in a vacuum.

What clicked

Two things.

First: thinking end-to-end before touching anything. Not just the customer flow — the architectural flow. Front to back, every connection, every place data moves. Once I started drawing that out before making changes, the dangerous surprises got rarer.

Second: backups are not optional. I knew this in theory. I understood it in practice only after I felt the weight of having live customers. Now it’s the first thing I set up on anything real.

The duct tape is slowly being hardened into real solutions. Bugs are getting out of the house. The owner is happy. Customers are booking. That’s the bar, and we’re clearing it.

Artifact

thebookingapp.co — live, in production, with real customers. A lightweight booking solution for spas and salons. Built by one non-engineer with AI tools, a terminal, and a lot of iteration.

If you’re starting

If you’re thinking about building something real — not a demo, not a prototype, something with actual users — the most important thing I can tell you is this: get a real test subject before you write a line of code.

Not an imagined customer. Not a friend who says “yeah that sounds cool.” Someone who has the actual problem, who will actually use the thing, and who will tell you when it breaks. That feedback loop is the whole game. Everything else is just building the car nobody drives.

Start simple. Ship the thing that solves the core problem. The rest can come later — and it will, once you know what “the rest” actually needs to be.

main
rss