← All writingField note / Full-Stack

· 1 min read

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.

  • Full-Stack
  • Architecture
  • NestJS
A service advisor, customer and technician working inside a modern automotive garage
Editorial project visualization · illustrative, not a product screenshot

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 if statements.

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.