EstimaService Quote Calculator
What it does for you
Customers get an instant price on your site.
A configurable instant-quote engine: a customer wizard with a live itemized total and an admin builder that edits the pricing rules.

Who it's for
Businesses that price by the job, like cleaners, detailers, and home care agencies, and lose leads while they work up a quote. You change the pricing rules yourself, without code.
Screenshots



In more detail
Estima lets a small service business publish an instant, itemized price quote that customers can fill in, save, and print. The owner can change the pricing rules without touching code. Cleaners, detailers, and home care agencies lose leads while they "get back to you with a quote," and most quote widgets are either a fixed price list or a black box. Here every line of the price is explained.
Honest limits
The admin builder clicks, the print dialog, and the mailto hand-off were checked by rendering views headlessly, not by clicking through every form in a real browser. Saved quotes live on one device. It works and the pricing math sits under 298 checks, but it's not hammered for production.
How I built it
It took a few sessions. Claude Code wrote the pure core in quote.js first (pricing models, the rule engine, promos, tax, deposit, presets, quote IDs, the embed snippet) with 269 assertions, before any UI existed. I set the rules up front: no eval, money in cents, every line explained. The first UI session died when the API stream dropped mid-write.
A second Claude Code session rebuilt the UI as a dozen small modules, and a final finishing pass of about 0.5 hours inspected what survived, fixed the gaps, added file and import-graph checks (298 green), took screenshots, and wrote it up. I directed the product choices: two faces from one config (a customer wizard and an admin builder at #admin), three presets (home cleaning, mobile detailing, home care hours), and a quote that prints like a real document.
What I learned
- A small tokenizer plus Pratt parser is enough for business rules like
sqft > 3000 and pets. A null-prototype scope and a list of forbidden names likeconstructorand__proto__close the obvious escape routes, with noevalornew Functionanywhere. The verify suite now scans every module in the import graph to keep it that way. - Keeping all money in integer cents made stacked bundle, promo, and tax math exact. A 15% promo on a bundle with tax never drifts by a cent.
- A config-driven UI is only as good as its sanitizer. Running every imported config through
sanitizeConfigandvalidateConfigmade the admin builder safe to break, and the live health check came almost free. - Demo data needs deterministic IDs. The saved quotes were seeded with
Math.random, so a deep link to#saved/IDbroke on every reload until a seeded generator made the IDs stable. - The finishing pass also caught an empty save that could throw and long email addresses breaking mid-word on the quote summary.
What carried forward
Integer-cent money is the same rule #41 Signet uses for its proposal pricing, and the pure core plus verify.mjs setup is the pattern I've used since #9. The fix for the dropped streams was process, not code: files under about 100 lines, one tool call at a time. That's the tiny-writes approach that finished most of this batch.
If I took it further
I'd put the quote ID and config version in a signed share link so a customer can reopen a quote on another device. Then I'd add real browser tests for the admin forms.
#048 Built with Claude Code September 23, 2026 298 automated checks