MRO Express โ a project by Ahsan Mahmood
A B2B parts-sourcing and on-demand delivery platform for HVAC, plumbing, and electrical contractors.
A part fails on a job and the day stops.
Not for the repair, which is often quick. It stops for the sourcing: identifying the exact replacement from a worn label, then finding who has one, at what trade price, near enough to collect. That is usually a sequence of telephone calls made while somebody stands in a plant room waiting.
Contractors call it the scavenger hunt, and it is the target here.
MRO Express is designed to collapse it: photograph the broken part, have it identified, compare live stock and contractor-tier pricing across distributors, and have a courier bring it to a coordinate on a job site rather than an address somebody has to leave to visit.
That is the design. Here is what is running.
An application shell with theming and observability. A marketing home built to be read in field conditions. The provider-contract scaffold beneath them both.
The record marks identification, aggregation, courier dispatch, payment splitting and accounting sync as roadmap, tracked as numbered work still to do. None of the interesting half is live, and the record says so about itself before anybody else can.
The scaffold is the interesting part. It is also an unusual choice.
Every external dependency sits behind a typed contract with two implementations: a free mock and a real one, selected by configuration. Five domains are built that way, covering vision, catalogue, courier, payments and accounting.
That has two consequences and both of them matter.
The whole product builds and demonstrates end to end with nothing provisioned and nothing charged, so development never waits on a commercial agreement with a distributor. And each domain flips to live independently, so the integration seam is designed deliberately rather than cut later under the pressure of a signed contract and a deadline.
Mock-first is slower at the start and it is the difference between a demo and a foundation.
Supabase carries the entire backend, and the domain is the reason.
Orders and pricing are relational. Matching a photographed part against a catalogue is a vector problem. Dispatching to a job site is geospatial. Those are three different capabilities, and Postgres carries all three through extensions rather than requiring three services with synchronisation between them.
Row-level security, realtime updates and server-side functions come from the same system.
So the backend is one thing. On a platform that would eventually settle money between a distributor, a courier and itself, the number of systems that must agree about who is allowed to see what is a real risk, and keeping it at one is the cheapest reduction available.
One more decision follows from working in the field rather than at a desk, and it shows up in the smallest places.
The shell carries theming with light and dark modes and accent and font switching, plus a loader that prevents the wrong theme flashing before the first paint. On a phone held in a plant room those are not decoration. Readability under bad lighting, in gloves, at arm's length is the difference between a tool somebody uses and one they put back in the van.
What it cost is excitement.
A product whose whole promise is the roadmap is difficult to write about without borrowing its future tense. The parts that exist are a shell and a set of contracts. That is honest and unexciting, and the alternative would be a page describing an identification feature that has never seen a photograph.
What it does, and what that costs to build
- Themeable app shell with dark/light mode, accent and font switching, and anti-FOUC loader
- AI Lens to identify a part from a photo via OCR and pgvector semantic matching (roadmap)
- Multi-distributor catalog aggregator with live stock and contractor-tier pricing (roadmap)
- On-demand courier dispatch with live position and status tracking via Realtime (roadmap)
- Stripe Connect escrow split settlement across distributor, courier, and platform (roadmap)
- QuickBooks / Xero accounting sync per order (roadmap)
- Mock-first integration spine with typed provider contracts selectable by env
- Env-gated logger, error, and analytics observability that never blocks boot
Built with
- React 19
- TypeScript
- Vite 8
- Tailwind CSS v4
- Radix UI
- TanStack Router
- TanStack Query
- Zustand
- Supabase
- Capacitor 8
- D3
- Dexie
Worth knowing
- b2b
- marketplace
- capacitor
- supabase
- react
- hvac
- parts-delivery
- on-demand
What works in MRO Express today?
A themeable application shell, a marketing home built for field conditions, and the provider-contract scaffold underneath both. The record marks the identification, aggregation, courier, payment and accounting features as roadmap, and tracks them as numbered work still to come. So the parts-sourcing product described below is designed and not running. The record calls its own state honest, and repeating that honestly here is the least this page can do.
What is the parts scavenger hunt?
It is the hour a contractor loses finding a component. A part fails on a job, the exact replacement has to be identified from a worn label, and then it has to be located across several distributors with different stock and different trade pricing, usually by telephone, usually while somebody waits. The work itself is quick. The sourcing around it is what actually consumes the day, and it is the thing this platform is aimed at.
What does mock-first mean and why does it matter?
Every external dependency sits behind a typed contract with two implementations: a free mock and a real one, chosen by configuration. Five domains are arranged that way. The product therefore builds and demonstrates end to end with nothing provisioned and nothing charged, and each domain can be switched to live independently. It means development never waits on a commercial agreement, and the integration seam is designed rather than discovered later.
Why Supabase for all of it rather than several services?
Because the domain needs several database capabilities that happen to live in one place. Relational data for orders and pricing, vector search for matching a photographed part against a catalogue, and geospatial queries for dispatching to a coordinate are three different problems, and Postgres carries all three with extensions. Row-level security, realtime updates and server-side functions come from the same system, so the backend is one thing rather than four with a synchronisation problem between them.
Does MRO Express work on iPhone?
There is no Apple release. One codebase targets web and mobile through Capacitor, and the record lists iOS among its intended targets, which describes configuration rather than anything published. No Apple Developer account sits behind this work and nothing I build has shipped to the App Store. What exists to open is the web address, which a phone browser reaches like any other page.
https://aoneahsan.com/projects/com.aoneahsan.mroexpress