01The rebuild
The booking rebuild
The clinic booked through a hosted widget it could not style, could not instrument, and could not extend. Bookings that came through it arrived in analytics with no source attached.
Front desk staff had used that flow for years.
A better flow that behaved differently would cost more in retraining and mistakes than it earned in elegance. Same order, same wording, same number of taps.
So the build ran in two passes.
- Write a booking flow from scratch against the API
- Walk the vendor’s own hosted widget, screen by screen, and rebuild the new flow to match it exactly
- Full service catalog with categories, a multi-treatment cart, and add-ons
- Provider selection with live per-provider availability
- A month-grid calendar that paints without spinners, using speculative prefetch on the dates a user is likely to open next
- A native date picker on mobile instead of a rebuilt one
- Card checkout through Boulevard’s card vault, so card numbers never reach our server
- SMS sign-in, with an account picker for clients who have more than one record
- A waitlist, location-aware phone numbers and promo codes, added after launch
- Tested end to end with a real appointment before launch
02The audit
Then I audited it
A build this size, going onto a live medical calendar, does not get to be trusted because its author feels good about it. It got a nine-area correctness audit, each area cross-checked against the vendor’s published SDK rather than against my own assumptions.
- ScopeNine areas, each cross-checked against the vendor’s published SDK
- Root causeTwo separate symptoms, one architectural mistake: the code sent changes to the booking system without reading the cart back, so the screens after service selection showed what the user intended rather than what the system actually held
- Also caughtA gap in the safeguard against test bookings
- OutcomeBoth fixed before cutover, along with a pass on the mobile layout
03Sign-in
Duplicate client records
Boulevard’s phone verification attaches the cart to an arbitrary record when one phone number belongs to more than one client, which is common in a clinic’s records.
Merge the duplicates in Boulevard, changing patient records to work around a sign-in bug.
Rebuild sign-in on Boulevard’s passwordless multi-client auth, with an account picker.
The working version mints signed, client-scoped access tokens on the server. The client ID only ever comes from Boulevard’s response to an SMS-verified phone number.
04Security
Security and tests
Cart binding
Each cart is bound to the browser that created it, through a cookie set by an uncached request because the host’s page cache strips cookies from page renders.
Pen test
Before launch the flow went through white-box penetration testing, and the launch blockers it found were closed before cutover.
Tests
The real booking modules run against WordPress stubs with no network, covering the launch blockers and promo codes. There is no CI; the deploy scripts lint every file on the server.
05Status board
The client status board
A different problem, same shape: build the interface the situation actually needs instead of accepting the one you are handed.
Working across seven surfaces for several owners generates a specific overhead, which is the same status question asked separately by different people and answered slightly differently each time. Written updates go stale the day after they are sent.
- Password-gated, hand-rolled, static, no framework, because a status board should not have a build step that can fail on the day someone needs to read it
- A Gantt-style timeline generated entirely from ISO dates, so nothing is positioned by hand
- A shipped log and per-project detail pages, all from the same source
- A presence system with working-hours logic, so the owners can see when I am working
- One editable data file drives every page, which is the only reason it stays current
The failure mode of a status document is that maintaining it costs more than the confusion it prevents, so it quietly stops being maintained. Collapsing every page down to one file was the whole design goal.