Work / Field service operations
Field service operations
Live demo belowBuilt for a plumbing company that was running its schedule on a whiteboard and its money in a spreadsheet. One record now follows the work from the first phone call to the paid invoice — and the customer can watch it happen without ringing the office.
- Client
- A plumbing company — name withheld at their request
- Our role
- Discovery, product design, full build, ongoing maintenance
- Scope
- Intake, quoting, dispatch, jobs, invoicing, reviews, customer portal
- Stack
- React · Node · PostgreSQL · iOS · SMS
This is a live sandbox, not a slideshow. The interface below is the real one, running in your browser against invented data — the client's own customers, technicians, and figures are not here. Click anything: nothing dispatches a technician, charges a card, or sends a message. Reload the page to reset it.
How it is built
A React front end for the office, a native iOS app for the technicians, and one Node API over PostgreSQL serving both. The technician app is native rather than a mobile web page for one reason: crawl spaces and mechanical rooms do not have signal, and the app has to keep working when the network does not.
One record, five stages
The single most important design decision here was refusing to build separate quote, job, and invoice systems. A work item is created at intake and moves through stages — requested, quoted, approved, scheduled, completed, invoiced, paid — accumulating rather than replacing information. That is why approving a quote can schedule a technician and open an invoice in the same click: they are not three records that need to agree with each other, they are one record with three faces.
Assignment
When a quote is approved the system picks a technician. In the demo that is a simple least-busy rule you can watch operate. In production it also weighs certification against the service — a backflow test can only go to a certified tester — plus drive time from that technician's previous stop and whether the customer has asked for someone they have had before. The dispatcher can always override it; the point is that the default is usually right.
Offline and the field
The iOS app holds the day's assigned work locally. A technician can arrive, open the job, photograph the failed part, add materials, capture a signature, and mark the work complete with the phone in airplane mode. Changes queue and sync when signal returns, with conflicts resolved in favour of the field — the person standing in front of the water heater is the authority on what was actually done.
Where the invoice comes from
Invoices are generated from the completed work item — the approved price, plus materials added in the field, minus anything the office writes off — and posted to the accounting package overnight. Ageing on the invoice screen is computed from terms on the customer record, so "Overdue" means overdue for that customer rather than a global thirty days.
What we would build next
- Route optimisation across the whole day rather than per-assignment.
- Maintenance agreements — recurring work that schedules itself and renews.
- Parts inventory on the vans, so a job can be assigned to whoever is already carrying the part.
Still dispatching off a whiteboard?
Service businesses lose more money between the quote and the invoice than anywhere else in the operation. That gap is usually a fortnight of work to close.