← All work
WL
Vertical SaaS · GCC · UAE launch

WashLink

● Live

A three-sided multi-tenant SaaS platform. Mobile car-wash businesses subscribe to run their operation, customers book washes performed at their own location, and the business's drivers carry them out.

Category
Vertical SaaS
Market
GCC · UAE launch
Surfaces
iOS · Android · Web · Driver app · Admin
Status
Live in production

Dispatch by WhatsApp, payment in cash.

Mobile car-wash operators coordinate drivers in group chats and take payment in cash at the kerb. There is no schedule, no dispatch, no record of what was done or what was earned — and no clean way for a platform to take its share.

WashLink gives each business a tenant of its own with staff, drivers, scheduling and settlement, and gives the platform a subscription business on top of it.

Every surface, by us.

Customer app
Flutter — book a wash at a location and a time, track the driver, pay in-app.
Driver app
The fulfilment side of the same Flutter codebase: the day's jobs, navigation and completion.
Business web
Next.js 15 — owners and managers run catalogue, staff, scheduling and reporting.
Platform web
Platform admin and staff, tenant management and commission configuration.

Three sides means three ways to get authorisation wrong.

A multi-tenant platform with money moving through it has to assume every guard will eventually be forgotten once.

// 01

Tenant scoping lives in the repository, not the controller

Every query touching business-owned data is scoped by business identity at the repository layer. The codebase is written on the explicit assumption that a controller-level guard will one day be left off a new endpoint.

// 02

Every endpoint declares its own access

An endpoint carries either an explicit permission requirement or an explicit public marker. There is no third option and no default, so an unguarded route is a review failure rather than an accident waiting to be discovered.

// 03

Split settlement at the acquirer

The customer pays once. The business's share settles to the business's own connected account and the platform's commission to the platform's, while the recurring SaaS subscription is billed separately. Payment state is set by webhook and never by a client redirect — a browser that never comes back from the payment page must not be able to leave an order in the wrong state.

// 04

Arabic and RTL from day one

New user-facing copy requires both English and Arabic keys to be accepted at all. Right-to-left was a day-one constraint, not a retrofit — which is the difference between a translated product and a bilingual one.

// 05

Time is stored in UTC and scheduled in the business's zone

All timestamps are stored as UTC, but every scheduling decision converts through the business's timezone — not the server's and not the customer's.

What it runs on.

NestJS 11 Prisma 6 PostgreSQL Next.js 15 Flutter Stripe Connect Turborepo Docker

We build these for ourselves. We build them for clients too.

Everything on this page was designed, built, deployed and is operated by the same small senior team. If you have a product that needs the same treatment, start with a conversation.