Chen Plumbing runs on technicians in the field, not a back office. AppMakers USA built the internal app they use to cost jobs, log materials, and restock, plus the engine underneath it that turns all of that work into payroll the business can trust.
Chen Plumbing is a family-run operation. Its plumbers spend the day on jobs, not at a desk, and for years the work that holds a trade business together (what parts went on which job, what they cost, what each plumber is owed) lived in manual lookups and memory.
AppMakers USA built the internal system that replaced all of that. It has two faces: a stripped-down field app a technician uses on the job, and an office console where the business sees everything roll up. The two had to be true at once, and they pull in opposite directions.
The people using it aren't engineers. If a screen isn't obvious, it doesn't get used.
The hardest design constraint wasn't a feature. It was translating a traditional, hands-on plumbing workflow into something a field technician (not necessarily a tech-savvy one) would actually reach for on a job, instead of falling back to paper.
So the surface had to disappear. A plumber pulls up a job, taps in the parts and pricing, marks a restock, and moves on. The surprise, building it, was how much the small calls decided everything: a field crew adopts a clean tool and quietly abandons an awkward one.
Costing a job, on the glass. A guided three-step flow (job info, POs and reimbursement, cost summary) that a technician finishes in the truck.
These screens show the app with realistic but fully anonymized sample data; the client's real records are protected under NDA.
Costing a job means adding materials, and a real job uses ten to thirty of them. Each one runs an autocomplete over a list of 781 parts. On long jobs the screen started dropping frames and creeping slower the more a plumber typed. A perfect field-adoption killer: the tool got worse exactly when the work got bigger.
The materials list was re-rendering every visible row on every keystroke, and the multi-select path rebuilt its arrays inside the render path: small leaks that compounded across a long session.
Two passes fixed it: move the selection into a ref so picking a part doesn't re-render the input, then stabilize every callback and memoize the row. Typing on a thirty-line job stayed flat and fast.
Got a team in the field that won't touch clunky software?
Get a Free Project Estimate →The same taps a plumber makes to cost a job (materials checked off, a commission rate, an emergency restock logged) are the raw inputs to payroll. The naive way to build that is to store each plumber's weekly total and nudge it as things change. It works until the day a corrected invoice doesn't match the commission already shown, an archived part still counts, and nobody can say which number is true.
So we didn't store payroll at all. We treat it as a calculation, not a saved value.
Whenever something that affects a plumber's pay changes, that week's payroll is re-derived from scratch from the jobs, materials, and restocks underneath it. The safeguard that makes this trustworthy is simple: once a job's invoice is marked completed, it's locked and can't be edited. A finished week's source data is frozen, so its derived total can never silently move. Any week can be regenerated from its rows on demand (an audit trail by construction) and an admin's manual adjustments sit cleanly on top of the computed numbers instead of fighting them.
The week, derived. Jobs, commission and reimbursements per plumber: none of it stored, all of it rebuilt from the source rows. Completed weeks lock; the current one stays live. (Illustrative data, anonymized under NDA.)
The real world doesn't fit "one supplier visit per job," so jobs were refactored to carry multiple POs and reimbursements. But a field app can't assume anyone updates it: plenty of plumbers only open the app to log materials, and half the fleet was still running the previous build.
An API shim flattens the new many-to-many shape back into the old single-PO, single-reimbursement shape based on each client's version header. The new app gets the rich data; the old app keeps working untouched. Every API change since carries the same question by default: what does the old client see?
Every job, in one place. The whole company's jobs, costed and tracked, where the office can see them.
These screens show the app with realistic but fully anonymized sample data; the client's real records are protected under NDA.
My guys actually use it. And at the end of the week, payroll just adds up.
A field-first app built plain enough that technicians reach for it on the job, replacing the manual lookups and paper a trade business usually runs on.
Every week is re-derived from its own jobs, materials, and restocks, with completed invoices locked, so a finished week is reproducible and can't quietly drift.
Old and new app versions run side by side through a version-aware API, so no plumber is ever blocked by an update they didn't install.
If the numbers that run your company live in spreadsheets and memory, you need software the field will actually use and an engine you can trust underneath it. We build that, and stay on to run it with you.
Get a Free Project Estimate →