Laravel Quote Estimator
A self-serve pricing tool on this bilingual site: seven questions, a real price on screen, no sales call and no waiting for a quote.
A buyer who will not pick up the phone still wants a price. The usual answer is a contact form and a promise to get back to them, which keeps the people who were shopping and loses the ones who were ready. So this site prices itself: seven questions, a real figure on screen, no call. The risk that comes with that is plain enough. A pricing tool nobody checks will show a wrong number confidently, and go on showing it.
The tool is a seven-step questionnaire that prices live as you answer, with a second configurator for custom work priced separately. A submitted estimate persists together with the answers that produced it, so a follow-up call starts from the buyer’s own numbers rather than from nothing, and an authenticated admin panel sits over what was captured. Everything is bilingual, including every generated figure. Rate limiting runs per caller with a per-IP ceiling, and the URL-analysis endpoint carries its own SSRF guard with its own test.
What we measured
What keeps it honest is a gate that runs before deploy. It walks 19 pages at 6 screen widths in both languages and checks 26 counters, cross-checking every figure between the JavaScript calculator, a Python port of the same model, and the PHPUnit fixtures. It exits non-zero if a single counter moves. Beside it sit 34 feature tests and 675 assertions. The gate has already caught a CSS rename that broke its own selectors, which is the useful kind of failure: a checker noticing that it can no longer see.
Why it holds
It also caught two defects a visitor would have hit. The live estimate and the final estimate shared one rate-limit budget, so ordinary use produced 41 calls and a 429 in 39 seconds, with 73 percent of the payloads byte-identical. Separately, the results summary preferred a cache that never expired, so the screen froze: the server was returning 720.50 CAD per month while the page still showed 136.50, silently, with no error anywhere. Both fell to one fix, fingerprinting the answers so a result is shown only when it was computed from what is currently on screen. After: 11 calls instead of 41, no 429 across 25 round trips, and the summary matching the pricing model to the cent.
The failure mode of a self-serve pricing tool is not a crash. It is a confident wrong number that nobody reports, because the visitor takes it for the price and leaves.
SCOPE AND LIMITS
The gate proves the three implementations agree with each other, and that no figure moved without someone deciding it should. It cannot prove the pricing model is commercially right: that is a business question and no test settles it. The counts describe the gate as it stands today and grow as the site does.
STACK
- Laravel 13
- PHP 8.3+
- Vite
- SQLite
- PHPUnit
- Playwright