Designing one platform for four kinds of users
What building a garage booking system for customers, merchants, staff and admins taught me about schema-first product work.

The Car Care System has four audiences: the customer booking a service, the merchant running a garage, the staff doing the work and the admins watching over everything. Each one needs a different product. They all share the same bookings.
Start with the schema, not the screens
It’s tempting to begin with the customer app because it’s the most visible. I started with the database instead. If bookings, services, bays and people are modelled well, four interfaces become four views of the same truth. If they’re modelled badly, you end up synchronising four copies of reality.
A few decisions that paid off:
- Roles are relationships, not user types. A person can be staff at one garage and a customer at another. Model membership, not identity.
- Bookings have a lifecycle. Explicit states make every role’s screen simpler, because each one just filters by the states it cares about.
- Merchants own their data. Scoping by garage from day one meant access rules were a property of the schema, not scattered
ifstatements.
Then design flows per role
With the data settled, the UI/UX work became about subtraction: what does this role never need to see? Customers don’t need bay schedules. Staff don’t need billing settings. Admins need everything, but summarised.
Backend shape
NestJS modules map cleanly onto the domain — bookings, garages, services, users — with Supabase underneath. Keeping modules aligned with the schema made it straightforward to deliver frontend and backend pieces in parallel.
Four apps in one system is manageable when there’s exactly one place where the truth lives.
The lesson I keep re-learning: most “frontend complexity” is a data-modelling problem wearing a disguise.