Multi-trade · AI automation
One engine, six businesses, and a price that never disagrees with itself
The website says one price, the estimator says another and the chat says something else. Every new location means rebuilding the logic.
Our own TypeScript engine runs six concept sites from one knowledge file each, so the page, estimator, assistant and dispatch agree.
Our own system. It runs inside our concept sites, such as Ridgewell Roofing, a fictional business.
The everyday problem
One knowledge file per business drives everything, so every page reads the same prices.
The hard part
- The estimator and the price table disagree
An estimate that scales nothing repeats the published price exactly, so a $175 call no longer shows as $200.
- 'Roof' matches every roofing service
Words guessed from service names lose to keywords the company declared.
- One company quoting another's prices
The business id is added on the server, never taken from the browser.
- A free inspection given a price
A $0 service is shown as free, never scaled into a price.
- A release that breaks live
Smoke tests run after the switch. If live fails, the previous release goes back at once.
How it runs
How one engine serves six businesses without mixing them up.
Sample run- Step 1: One knowledge file per business.
- Step 2: All read the same file. Page, estimator, assistant and dispatch.
- Step 3: Business id added on the server. One company can never quote another's prices.
- Step 4: Own database per business. Additive migrations on open.
- Step 5: Release automation. Smoke tests, automatic rollback.If this fails: Live check fails: rolls back.
Tap “On fail” to see what happens when a step breaks.
Edge cases we handled
| When | What the system does | Try it |
|---|---|---|
| A database was made before a new column existed. | The column is added on open. Nothing is lost. | No phrase to try |
| A browser sends a forged site id. | It is never read. The server adds its own. | No phrase to try |
| A visitor prices a roof in the 3D configurator. | That price goes on the lead as the estimate. It is not recomputed. | No phrase to try |
| The live smoke test fails. | The previous release is put back. | No phrase to try |
Guardrails and hand-off
Guardrails
- The business id comes from the server, never the browser.
- Each business has its own database file.
- Migrations only add columns, never drop them.
- No release stays live after a failed smoke test.
When a person takes over
Every site writes its leads and steps to its own office board. People pick up from there.
Not in this build yet
We would rather you hear it from us.
- Twenty-eight unit tests cover the chat flow and the public board's privacy. The scoring, matching, estimating and dispatch functions have no tests of their own yet.
- Confirmation messages are logged only. No text or email goes out, and each log line says so.
- The booking form prices a job as routine; a lead the server records can carry the after-hours rate for an emergency, so the two can differ.
Built with
- TypeScript
- Next.js
- Node.js