[ Case study ]
Members booked classes through a dashboard that had grown feature-by-feature for two years. The booking flow took nine interactions across three pages, support tickets showed members giving up, and the component code had no shared state model — every fix risked breaking another.
CLIENT a fitness-booking startup — FOCUS Model the state before the screens
Representative examplesEvery case study in this library is an illustrative composite of the kind of engagement we deliver — written to show our method and standards, not to name clients.
This startup runs class booking for boutique fitness studios — members buy passes, browse schedules, and book through the web dashboard. The frontend grew feature-by-feature across two years of startup pace: waitlists, pack purchases, instructor substitutions, each bolted on by whichever developer was free. Members book mostly on phones between classes. The in-house team knew the dashboard had become fragile, and knew equally well that nobody could pause bookings to fix it.
Members booked classes through a dashboard that had grown feature-by-feature for two years. The booking flow took nine interactions across three pages, support tickets showed members giving up, and the component code had no shared state model — every fix risked breaking another.
We proposed modeling booking state first — schedule, waitlist, and passes in one typed client store — then rebuilding the flow to a single schedule view with an inline confirm, shipped screen by screen behind flags per member cohort. The rate-limited booking API set the rules: reads get cached and batched, mutations get optimistic UI with honest pending states, and the frontend stays inside quota even on Saturday mornings. Accessibility criteria — keyboard paths, screen-reader labels — were acceptance criteria for every screen, not a phase.
Just as important is what we ruled out, and why:
We mapped booking state (schedule, waitlist, passes) into one typed client store, then built screens against it — eliminating the cross-page inconsistencies.
The nine-step flow became a single schedule view with an inline confirm, designed against the task, not the old page boundaries.
Each replaced screen toggled per cohort, so regressions surfaced in days on real bookings instead of at a cutover.
Delivered by the experience pod — frontend engineer + designer over 8 weeks, with working increments reviewed with the client every week.
Obstacle
Load testing in week three tripped the booking API's rate limits — the redesigned flow made more calls per booking than the one it replaced.
Handled: Their account manager renegotiated the booking API's quota mid-build — the negotiation we now say belonged in week one — and the caching layer for schedule and capacity reads was sized to the renegotiated headroom rather than asked to absorb the ceiling.
Obstacle
Cohort flag rollouts confused the support team, who were answering two members on the same day who were seeing different dashboards.
Handled: We gave support a flag-state lookup and a one-line explanation script, pinned cohorts to member IDs, and the contradictions stopped within a week.
The headline: median time from dashboard open to confirmed booking, measured over 6 weeks of usage after full rollout — −38%, read from Product analytics event timing. A second check: booking-abandonment support tickets at −31%.
The developers ship dashboard changes without the pre-change shudder; the typed state model made cross-feature breakage a compile error instead of a support ticket. Support talks to product about features now rather than translating member complaints. Members finish bookings on the first screen they land on, and the cohort flags came down because nobody needed a safety net anymore. The booking flow stopped being the app's apology.
The result was read from Product analytics event timing against the pre-engagement baseline over the stated window, with a guardrail check on booking-abandonment support tickets. Where platform-reported numbers and business outcomes differ, this record says which layer it is quoting.
What we would do differently
We would have negotiated API quota headroom earlier — rate limiting forced a caching layer we should have specified in week one.
[ Related service ]
[ Related builds ]
9 installs 1 adminSites maintained from one WordPress admin, migration completed over 9 weeks
3 weeks 4 daysMedian landing-page turnaround, measured across the first 12 campaign pages post-handover
[ Next step ]
Next case study