Merge fields that pull real project numbers into the contract

27 named placeholders — customer, builder, project, estimate, governing law — that resolve per customer when the contract is generated.

What it is

A `{{section.key}}` grammar with dot access, rendered by renderTemplate. Missing tokens render as empty strings so a partially-filled intake form never breaks the document. The token set spans builder identity ({{builder.company_name}}, address, phone, email), customer ({{customer.legal_name}}, mailing address, source of funds, lender clause, co-signer clause), project ({{project.address}}, start/end date, material payment due date, building type, duration), estimate ({{estimate.total}}, material_cost, labor_cost, markup, payment_schedule, line_items_table, subtotal, tax) and governing law (state + notice).

Also called: contract tokens · placeholders · auto-fill contract · {{tokens}} · mail merge contract

See it
Merge fields that pull real project numbers into the contract
Prepared for
Gideon Alt
1140 Ridge Line Rd · Fair Play
Shell package$28,663
Concrete & site$8,321
Doors & windows$5,548
Trim & finish$3,698
Total
$46,230
Signature
The token reference table (monospace token in accent colour, description beside it) beside the editor with a highlighted {{estimate.total}} resolving to a real dollar figure in the preview. IntakeSettingsTab.tsx TOKEN_REFERENCE. Sample data — no customer information appears here.
How it works
  1. 1TOKEN_REFERENCE in the settings panel lists every token with a description.
  2. 2buildContractContext() assembles the context from the estimate link, the intake form data, the estimate snapshot and the builder's invoice_settings.
  3. 3renderTemplate() substitutes with a regex over `{{ token }}`, walking dotted keys and returning '' for anything missing.
  4. 4Derived tokens are computed, not just copied: end date falls back to start + duration days, material payment due date is start minus 30 days.
Why we built it

The rule that missing tokens render empty is deliberate: 'Missing tokens render as empty strings so a partially-filled form doesn't break the output.' A contract that throws or prints `{{customer.legal_name}}` in front of a customer is worse than one with a blank.

The problem
  • Copy-paste mistakes between estimate and contract
  • Dates and totals that go stale between drafting and sending
  • One template that has to serve every customer
Sound familiar?
What you get
The number in the contract is the number in the estimate
Dates derive themselves from the build schedule
A blank field never breaks the document

See it on your own jobs

Twenty minutes, your numbers, no slide deck. We’ll build one of your real buildings in front of you and send you the estimate link at the end — yours to keep either way.

or keep browsing features →