A dry cleaner with collection and delivery across a defined coverage area, taking bookings by phone and tracking them on paper.
Service booking · Nuxt & Laravel
JACOBS Drycleaners
Booking and customer management for a UK service business.
- Product
- JACOBS Dry Cleaners — booking and customer management, UK
- Role
- Full-stack developer, Global Shopaholics LLC
- Scope
- Nuxt.js front end on a Laravel 8 API, booking flow, staff admin

The tension
Two audiences, one system, and only one of them will ever read a manual.
Staff needed an admin area at least as much as customers needed a booking form, so the build was two interfaces over one data model rather than a website with a form on it.
A customer booking a collection without calling, and staff managing that order without transcribing it.
The service is geographically bounded. A booking outside the coverage area is worse than no booking, because someone has to unwind it.
The product story
Answer the two questions that stop a booking.
The offer
Professional cleaning, a few clicks away.
The landing view states the service and puts booking in reach, with the service promise close enough to be read before committing.

Narrow first
Booked from a phone, usually.
The Nuxt layout reflows to one column and keeps the booking action reachable without scrolling back up.

The two blockers
Do you cover me, and what does it cost?
Coverage area and price list are first-class pages rather than footer links, because they are the two questions that end a booking before it starts.

Walkthrough
The booking flow in motion
Recorded from the live site.
The trust test
The happy path is only half the product.
The address is outside the coverage area
Coverage is checked against the booking rather than assumed, so an out-of-area request is refused at entry instead of being accepted and unwound by a person.
A staff member and a customer act at once
Order state lives on the API and both interfaces read it, so a status change is not something one side can miss because it was holding a stale copy.
The visitor arrives from search, mid-funnel
Every page is server-rendered and self-contained, so a customer landing directly on prices or coverage gets a page that works rather than a fragment of a flow.
The decisions
Three moves carried the story.
Make coverage a page, not a footnote
The service only exists inside a delivery radius, so the coverage area is navigation-level content — the cheapest possible place to lose an out-of-area booking is before it is made.
Server-render the marketing surface
Nuxt SSR so the service, coverage and pricing pages are indexable for a business whose customers find it by searching its town.
One API, two consumers
The Laravel 8 API serves the customer booking flow and the staff admin from the same models, so an order has one representation rather than two that drift.
What I would test next
