Every version of this email has already been sent to them a hundred times. Someone they have never heard of, offering a website, attaching a portfolio, asking for twenty minutes on a call. It asks the owner to picture a thing that does not exist and then pay for it, and picturing things is work. Deleting the email is not.
So the order got reversed. Build the site first, finished, with their name on it. Then the first message is not a proposal, it is a link. There is nothing to imagine and nothing to agree to before looking.
An hour of research before a line of code
The shop is a real one. Four and a half stars, a hundred and thirty odd reviews, seven years on the same street. Their existing website has none of that on it. No prices, no opening hours, no address, and no way to contact them except a phone number.
The research is the pitch. The site is just where I put it.
All of it was sitting in their Google Business Profile, which is public and has an API. Real opening hours, real rating, real review count, and the five most recent reviews with the names attached. That last part matters more than it sounds: the reviews name the barbers. So a page that would otherwise have needed invented staff got real first names, from customers describing what each of them is good at.
It also corrected me. I had pulled hours off an aggregator site first, and they were wrong in a way I would never have caught by eye: it had the shop open on Sunday, and open later on Fridays and Saturdays. The real profile says closed Sundays and the same hours six days a week. That is not a cosmetic error. The booking calendar generates its slots from those hours, so the demo would have cheerfully offered a stranger a Sunday afternoon appointment at a shop with the lights off.
The research killed the obvious pitch, then gave it back
The plan was to sell them online booking. Their site takes bookings by phone call, which means every booking interrupts whoever is mid-haircut.
Then one of the Google reviews mentioned, in passing, that booking was easy because it went through Booksy. So they already had online booking, and pitching it would have told the owner in the first paragraph that I had not actually looked. The pitch changed to the thing their website genuinely does not do: say what anything costs, when they are open, or where they are.
Except a review is not a fact, it is a fact with a date on it. That one was six months old, so I opened the booking page it was talking about. It is gone. Booksy answers that link with its own deleted-business flag and bounces you to a list of other barbershops in the city. Their Google listing has no booking button either, and their website has never had one. Two of the barbers still have personal Booksy pages, which is a different thing entirely: you can book a specific man if you already know which one, but you cannot book the shop.
So the honest position moved twice in one evening, and only the second move was right. The demo keeps its booking flow, and the offer is now the plainest one available: right now there is no working way to book you online, and the review that says otherwise is out of date.
The lesson I would keep is smaller than that. Every claim I pulled out of the research had a timestamp on it, including the flattering ones, and the only one that mattered was the one I thought to re-check.
The part that is actually hard
A booking form looks like a form. The difficulty is not the fields, it is that time has rules.
Services stack. Somebody books a haircut and a beard trim together, so the appointment is not thirty minutes any more, it is fifty, and every offered time has to move. The slot generator only offers start times where the whole appointment finishes before closing, so a fifty minute booking stops being offered earlier in the evening than a fifteen minute one does.
The trap is the second change. Pick a short service, take the last slot of the day, then go back and add another service. The appointment no longer fits, but the time is still sitting there selected, and a form that trusts it will confirm a booking that runs half an hour past closing. So the chosen time is re-checked against the new total on every single change, and silently cleared if it no longer fits. Same when the barber changes, because a different barber has a different day.
That is the one piece of real logic in the file, so it is the one piece with a test. There is a small block of assertions at the bottom of the page that runs on every load: that no slot is ever offered past closing, that a stacked booking never offers more times than a single service, that the stale time is rejected, that the calendar file starts and ends at the right hours, and that the phone validation rejects junk. It is not a test suite. It is the smallest thing that fails loudly if the only tricky part breaks.
What is real and what is not
The hours, the rating, the review count, the reviews and the barbers' names are real. The prices are invented, because the shop publishes none anywhere, and that is the one thing I cannot research my way to.
So the demo says so. There is a banner across the top that names exactly what is real and what is a guess, the page carries a noindex tag so it can never compete with the client in search, and the phone number is from the range reserved for fiction, so no matter who finds the URL it cannot ring the owner.
That last one is not politeness, it is the difference between a demo and a liability. A public page with a real business's name, invented prices and their real phone number on it is a page that can send a stranger to them expecting a thirty dollar haircut.
And the invented prices are the hook. The email ends by asking what they actually charge for a cut and a beard trim, because it is the one thing genuinely not findable, it takes five seconds to answer, and an owner correcting the numbers on a website with his name on it has already started thinking of it as his.
The bottleneck was none of this
The build took an evening. Finding a way to contact the owner took longer.
Dubai to New Hampshire, and none of the usual channels exist. They do not use WhatsApp. An international text from a UAE number arrives looking like exactly the kind of message people delete. Their website lists no email, their contact page has no form, and the state business registry gave a company name and nothing to write to.
The email was eventually sitting in the About tab of a Facebook page with zero followers and one post, which the owner almost certainly set up once and never opened again. That is now the first place I look, before anything else, because it turns out to be where small business owners leave an address they have forgotten they published.
Which produced the rule I would keep from all of this: check you can reach someone before you spend a night building for them. A demo you cannot deliver is just a nice evening.
