● pricing and document automation · in production

The
Quoting
Desk

Two tools built for a freight insurance brokerage, covering one job end to end. The first prices an enquiry: every account carries its own negotiated rates, deductible ladders and permitted categories, configured in an admin panel rather than in code, and never visible to another account. The second assembles the certificate terms from the same answers, choosing clauses by rule.

Next.js 14 JavaScript Supabase Resend Edge Middleware Vercel
view live demo ↓
how it works
01
Rates as a matrix, not a formula
A price resolves through rate group × transit method × coverage type × value band. Each cell holds its own rate and minimum premium, and any cell, or any single band inside it, can be marked price on request instead of being quoted automatically. Adding a new commercial arrangement is a configuration change, not a release.
02
Every account isolated
Clients sign in with their own access code and see only their own negotiated terms, falling back to standard rates where no override exists. The whole configuration is assembled server-side and scoped to the session, so one client’s deductible schedule can never reach another’s browser.
03
Deductible ladders and availability rules
Deductibles resolve automatically from cargo value and coverage type: standard, or a ladder specific to one rate group. Availability rules express what simply cannot be sold in a given combination, so an impossible quote is refused with an explanation rather than priced wrongly.
04
Configured in an admin panel
Four screens: accounts and their access codes, standard terms across five tabs, the quote log, and the change log. Rates, ladders, categories, thresholds and client-facing texts are all editable there. Nothing about pricing lives in the source code.
05
A quote log that holds up
Every calculation is recorded: money, shipment, route, contact. All of it filterable by date, account and free text, with CSV export. Quotes that need a human are flagged as such rather than inferred later. Deleting a row takes two deliberate clicks, and there is no bulk delete: one wrong filter would take real history with it.
06
And a change log behind it
Every edit made in the admin panel goes to a separate log: what changed, when, and for which account. It is written only once the change itself has succeeded. When a client asks why their rate moved, the answer is in the system rather than in someone’s memory.
0
rates written in code
4
admin screens
3
isolated access roles
1
shared pricing rule set
Tech Stack
Next.js 14 JavaScript Supabase Resend Edge Middleware Vercel
what changed
before
A quote took a person and a day
A customer filled in a form on the website. It reached a member of staff, who looked up what that customer had been quoted before, built a new quote from it by hand, and emailed it back. Every routine enquiry consumed someone’s attention, and the customer waited.
after
The routine ones answer themselves
The customer fills in the same form and has the price immediately, then goes straight on to buying the policy. Which combinations of parameters and goods are priced automatically is set per account. Everything outside them still arrives as a request and is reviewed individually. Standard business stops consuming anyone’s day; the judgment calls still get judgment.
now
Live, with customers moving onto it
The system is in production on the client’s own domain. Accounts are being migrated onto it in stages rather than all at once, which is what the per-account configuration is for: a customer can be switched over as soon as their terms are entered, without waiting for anyone else.
the other half: terms

A price is only half of a quote. The rest is the certificate: which clauses apply to this shipment, for this client, at this value. That was assembled by finding a similar certificate and copying it, or by pulling clauses out of a Word file that was only as good as whoever last maintained it. Rare cases were usually not in the file at all, so someone went hunting through old certificates for the one that matched. How long it took varied, and the time was never really the problem: a certificate built by copying an old one inherits whatever the old one got wrong. The second tool compiles it from the same answers the price came from.

01
Four kinds of clause, on purpose
Automatic clauses fire on their own. Optional ones are offered as a tick. Templates stand in for a whole client-specific set. And reminders never reach the document at all: they only tell the person to check something. Deciding what not to automate was most of the design.
02
Rules live in a file the team edits
The clause set sits beside the tool as data, with its own schema version and a migration chain, so a new version of the tool has to carry the existing rules forward rather than reset them. Every save keeps a backup of what was there before.
03
Blocked clauses stay visible
A clause switched off for a given combination is not silently dropped. It appears under the optional ones, labelled with what blocked it, and can still be added to a single certificate. Hiding it would mean nobody ever notices a rule is wrong.
04
Duplicates removed, substitutions filled
Two rules often reach for the same sentence. The compiler keeps the first, drops the rest and says it did. Names, values and thresholds are filled from the form, so the goods on the certificate read the same as the goods on the quote.
05
No server, and nothing leaves the machine
It runs as a single file in a folder the team already shares, opened in the browser. No hosting, no login, no deployment, and nothing to maintain. Cargo values and client terms never travel anywhere, which for a brokerage is a reason to choose it rather than a limitation to apologize for.
06
Where a new rule actually lands
The quieter failure was not the copying. When the business changed a rule, it reached the team unevenly, and people applied it differently or not at all. Now a change is made once, in the rules, and every certificate issued afterwards carries it. That part was never a software problem; it was a process one, and it is the reason the tool exists.
where else this fits

This one happens to be insurance, but none of the engine is. Strip the vocabulary away and the same situation keeps turning up: this customer has their own agreed terms, the price depends on a few things and on how big the order is, some of it we’d rather quote by hand, and in six months someone will ask why it cost what it cost. Plenty of businesses are still holding all of that in a spreadsheet and somebody’s memory.

01
Wholesale & distribution
Customer-specific price lists, volume breaks and promotional periods across a large catalog: the same matrix, with customers in place of accounts and SKU groups in place of rate groups.
02
Freight & logistics
Lane-based rate cards with contract pricing per shipper, surcharges by service level, and quotes that need to be reproducible months later when they are questioned.
03
Equipment rental & leasing
Rates by asset class, duration band and customer agreement, with deposits resolving the way deductibles do here.
04
Fabrication, trades & service contracts
Estimates built from materials, labour and margin rules, where each client has their own agreed terms and the quote has to be sent, logged and defended.
try it
Interactive Demo

The production system holds a client’s negotiated rates, so it is not something to open to the public. This demo is the same pair of tools configured as a wholesale drinks distributor instead, on entirely invented data, which also happens to be the point: nothing in either of them is about insurance. Sign in as different accounts to watch the terms change, then switch to the admin view to see where they are set.

open the interactive demo ↗

quoting from a
rate card
in a spreadsheet?

get in touch ↗ back to portfolio