Product Block 03 · Sellable today

Quote / Estimate Generator

Customer uploads a photo. The AI quotes the job. PDF or DocuSign goes out the same day.

Deploy: 3 days $3,000 setup $500/mo
Live demo Try the demo → https://estimate.cafecito-ai.com/

Best fit: HVAC, roofing, painting, pool service, marine repair, signs, custom millwork — any trade where the estimate is the bottleneck between lead and close.

⚡ Self-bootstrap · paste into Claude Code or Codex

Quote / Estimate Generator — build it without writing code

Drop the prompt below into Claude Code or Codex. The agent picks a contractor prospect, maps their pricing formula by interview, builds the photo-upload + Claude Vision + branded PDF flow, deploys it, and produces a real estimate from a photo of THEIR truck as the cold-pitch artifact.

You provide

You provide: (1) a contractor prospect slug (or a website URL), (2) their typical pricing formula (15-min phone interview), (3) the contractor email.

You get back

You get: a hosted photo-upload form on a sub-route, a sample branded PDF estimate using a photo of their own truck/sign, a 90-second Loom of the photo→quote flow, and a draft cold pitch with the PDF attached.

Runtime & cost

Roughly 90 minutes wall-clock + 15 min for the formula interview. ~$2-3 in Claude Vision tokens during testing.

📋 Copy the entire block below into Claude Code (`/plan`) or Codex
You are building a Quote / Estimate Generator (Block 03 in the Cafecito AI new-hire playbook). Full reference at https://cafecito-ai.com/new-hire/blocks/03-quote-estimate-generator. Read it. Use plan mode. Stop at every [GATE].

INPUTS YOU NEED FROM THE HUMAN (ask before doing anything else):
1. Contractor prospect slug or URL (HVAC / roofing / painting / pool / marine / signs / millwork)
2. Their typical pricing formula — get this in a 15-min phone interview using the question template below
3. Contractor email for the cold pitch

PRICING FORMULA INTERVIEW QUESTIONS (have the human ask the contractor, then paste the answers here):
- Base labor rate or pricing unit (e.g. $X/hr, $Y/sq ft, $Z/unit)
- Materials markup (%)
- Travel surcharge by zone (Miami area)
- Job tier multipliers (residential / light commercial / commercial)
- Minimum charge, dispatch fee, emergency rate
- Standard inclusions and exclusions

ENVIRONMENT (verify):
- Working dir: /home/eratner/cafecito-ai
- Cloudflare account: f7a9b24f679e1d3952921ee5e72e677e
- Wrangler authenticated via OAuth
- Reference scaffold: /home/eratner/asp-pool-season/ (closest pattern — pool intake)

SECRETS TO CONFIRM:
- ANTHROPIC_API_KEY (with claude-opus-4 vision access)
- RESEND_API_KEY

THE PLAN:

STEP 1 — RESEARCH + PRICING FORMULA (10 min plus 15-min phone interview by human)
- Pull contractor's site: hero text, services, brand color, logo URL, license number.
- Pull last 5 Google reviews + competitor screenshots.
- Wait for the human to complete the 15-min pricing interview. Don't proceed without the formula.
[GATE 1 — show research summary + parsed pricing formula JSON, ask "proceed?"]

STEP 2 — SCAFFOLD WORKER (10 min)
- Create /home/eratner/cafecito-ai/quote-<prospect-slug>/.
- Use Prompt #2 from the block page ("CF Worker + R2 + PDF scaffold") with the prospect's data + formula.
- Generate worker.js + wrangler.jsonc + D1 migration.
- Bindings: D1 QUOTES_DB (`wrangler d1 create quote-<slug>-db`), R2 QUOTES_R2 (`wrangler r2 bucket create quote-<slug>-r2`).
[GATE 2 — show worker.js, ask "deploy this scaffold?"]

STEP 3 — VISION PROMPT (5 min)
- Use Prompt #1 ("Vision-to-quote prompt") with the formula from Step 1.
- Save to /home/eratner/cafecito-ai/quote-<prospect-slug>/vision-prompt.md.
- Wire into worker.js as the Claude Vision system message.
[GATE 3 — show generated prompt, ask "this matches their pricing logic?"]

STEP 4 — PDF TEMPLATE (10 min)
- Use Prompt #3 ("Branded PDF template builder") with prospect's logo URL + brand color + license #.
- Generate the HTML/CSS template; render via Workers PDF service or @cf/svg2pdf.
- Test render on a sample submission with hardcoded data.
[GATE 4 — show the PDF render in browser preview, ask "looks like their brand?"]

STEP 5 — DEPLOY (5 min)
- Set secrets: ANTHROPIC_API_KEY, RESEND_KEY, CONTRACTOR_EMAIL, CONTRACTOR_PHONE.
- Set vars: CONTRACTOR_APPROVAL_REQUIRED=true (default for week 1), PRICING_FORMULA_JSON=<the formula>.
- Apply D1 migration. Deploy via OAuth wrangler.
- Print the live form URL.
[GATE 5 — print URL, ask "submit the first test photo now"]

STEP 6 — THREE-PHOTO TEST PASS (15 min)
- Wait for the human to submit 3 photos: a roof, a wall, a damage closeup.
- Verify each: vision read accuracy, pricing range sanity, PDF rendering, email delivery.
- Edit prompt or formula on misfires. Redeploy. Re-test.
[GATE 6 — confirm 3/3 PDFs sane, ask "ready for the cold-pitch artifact?"]

STEP 7 — GENERATE THE COLD-PITCH ARTIFACT (10 min)
- Tell the human: "Take a photo of the contractor's truck OR a wall on their site OR their shop sign. Submit it to the form with a fake job context (e.g. 'paint my back wall')."
- Wait for the resulting PDF.
- That PDF IS the cold-pitch attachment.

STEP 8 — RECORD THE LOOM + DRAFT THE PITCH (10 min)
- Use Prompt #4 ("Real-photo cold pitch") with: the PDF URL, the photo source description, the form URL.
- Tell human to record a 90-second Loom of the upload→PDF flow.
- Output: subject + email body + WhatsApp message + the PDF as attachment.
[GATE 7 — show the draft, ask the human to approve / edit / send manually]

STEP 9 — SHIP THE SUMMARY
- Single-line: "[CONTRACTOR] quote generator live at [URL] · sample PDF: [LINK] · pitch sent to [EMAIL]."
- Append to /home/eratner/cafecito-ai/quote-shipped.md.

DONE. End plan.

GUARDRAILS: never deploy without the pricing formula. Cost ceiling for testing: $5 in Vision tokens. Always require 2-3 photos minimum. Never auto-send to customer without contractor approval gate ON.
01Stack
  • CF Worker
  • R2 (image storage)
  • Claude Vision
  • PDFKit / DocuSign API
  • Resend
02Live references

Working production examples. Read the code. Steal the pattern.

  • ASP Pool Season Pool-opening intake → estimate workflow (closely related)
03Day-1 plan

A real prospect. A real demo. A real outbound message — all before 5pm.

  1. 09:00–09:30 Pick a contractor whose quote process is broken.

    Roofing, HVAC, painting, marine, pool. Call them as a fake customer at 9am. Time the path from call → estimate-in-hand. The slower their existing flow, the bigger your wedge.

  2. 09:30–10:30 Map their actual estimate logic.

    Get them to walk through how they price a typical job. Labor units? Per-square-foot? Materials markup? Tier (residential / commercial)? Travel surcharge? Write down the formula. Claude doesn't invent prices — it reads the formula you give it.

  3. 10:30–11:00 Stand up the photo-upload form.

    CF Worker + R2 for storage. Form: photo (required, multiple), address, contact, "describe the job" textarea. Mobile-first, drag-drop on desktop, camera-capture on mobile.

  4. 11:00–12:00 Wire Claude Vision for the read.

    Use claude-opus-4 with vision. Prompt asks for: dimensions estimate, materials needed, condition rating, complications visible. Output JSON. Always require 2-3 photos minimum (different angles).

  5. 12:00–13:00 Build the pricing engine.

    Pure JS function: takes Vision JSON + the contractor's formula → returns labor + materials + total + a price RANGE (not point estimate). Always include a "tech will confirm on site ±20%" line.

  6. 13:00–14:00 PDF generation + email out.

    PDFKit generates a branded estimate. Resend emails it to the customer + the contractor simultaneously. Subject: "Estimate for [JOB] at [ADDRESS] · [PRICE RANGE]". Include the photos.

  7. 14:00–15:00 Build the contractor approval gate.

    V1 sends to customer immediately. V2 (recommended): contractor gets a one-click approve/edit email FIRST, then it goes to customer. The approval gate is what they'll pay for once they trust the system. Build the toggle on Day 1.

  8. 15:00–16:00 Three-job test pass.

    Take 3 photos yourself: a roof, a wall needing paint, a ceiling water stain. Submit each. Verify range, formatting, PDF, email. Note every fault — fix the showstoppers.

  9. 16:00–17:00 Send the cold pitch with a real estimate.

    Take a photo of THEIR own truck or shop sign. Run it through your form. Email them the resulting estimate as your proof: "this is what your customers would have gotten in 90 seconds."

04Best practices & gotchas
  • Always require 2-3 photos from different angles. Reject single-photo submissions.

    Why: Vision models confidently hallucinate from one photo. Two angles cuts the error rate in half. Three is the sweet spot. Build the multi-upload as a hard gate, not optional.

  • Quote ranges, never point estimates. Always include "tech confirms on site ±20%."

    Why: Customers anchor on the number you give them. A point estimate of "$2,400" becomes "you said $2,400" when the tech sees the actual job is $3,100. A range "$2,200–$2,800" + the disclaimer protects the contractor and is more honest.

  • Separate labor and materials in the output. Always.

    Why: Customers read materials as a fixed cost (it is) and labor as negotiable (it isn't, but they think so). Showing the breakdown makes the price feel earned, not invented.

  • Detect customer language from the address + name + textarea. Default to bilingual output.

    Why: In Miami a "Garcia, 1200 SW 8th St, paint mi pared trasera" submission gets an English-only PDF and the customer ghosts. Generate both languages by default.

  • Store every photo in R2 forever. Tag with submission ID + timestamp.

    Why: Insurance disputes, "the damage wasn't there before," contractor liability cases all hinge on what the original submission showed. Storage is $0.015/GB/mo. Never delete.

  • Require photo + address + contact for triage. Reject submissions missing any one.

    Why: Photo without address = can't price travel. Address without photo = no scope. Either without contact = unable to follow up. Building the gate at submit-time saves the contractor from chasing 30% of his leads.

  • Build the contractor approval gate from Day 1, even if v1 ships without it.

    Why: V1 may auto-send to customer for speed. The day you have a wrong-by-2x estimate go out, the contractor wants the gate. Adding it later is a re-architecture; building it as a feature flag from day 1 is twenty extra lines.

05Prompts (copy-paste)

Drop these into Claude Code. Replace the [BRACKETED] fields with the prospect's details.

Prompt 1 Vision-to-quote prompt

The Claude Vision system prompt that reads photos + the contractor's formula and returns structured pricing JSON.

You are a quoting assistant for [BUSINESS NAME], a [trade] contractor in Miami. You read 2-3 photos of a job and return a structured estimate.

Pricing formula:
- Base labor: [$X per hour OR $Y per square foot OR $Z per unit]
- Materials markup: [X%]
- Travel surcharge by zone: [list zones + flat fees]
- Job tiers: residential / light commercial / commercial — multiplier [X / Y / Z]
- Standard disclaimers: minimum charge $[X], dispatch fee $[Y], emergency rate +[X%]

Inputs:
- 2-3 photos of the job site
- Address + zip
- Customer language (auto-detected)
- Optional: customer description

Output JSON only:
{
  "scope_summary": "1-2 sentences",
  "dimensions": { "estimate": "...", "confidence": "low|medium|high" },
  "materials": [ { "item": "...", "qty": ..., "unit_price": ..., "subtotal": ... } ],
  "labor_hours_estimate": { "low": ..., "high": ... },
  "labor_subtotal_range": { "low": ..., "high": ... },
  "materials_subtotal": ...,
  "travel_surcharge": ...,
  "total_range": { "low": ..., "high": ... },
  "complications_visible": [ "..." ],
  "needs_site_visit_for": [ "..." ],
  "disclaimer": "tech will confirm pricing on site ±20%",
  "language": "en|es"
}

If fewer than 2 photos, return: { "error": "need_more_photos", "instructions": "Please add a wider angle and a closeup." }
Never invent dimensions. If you can't estimate, mark confidence: "low" and add to needs_site_visit_for.
Prompt 2 CF Worker + R2 + PDF scaffold

Scaffolds the entire quote-generator worker.

Build me a Cloudflare Worker that handles photo-upload quoting for [BUSINESS NAME].

Endpoints:
- POST /api/quote → multipart/form-data (2-3 photos + address + contact + language). Stores in R2. Calls Claude Vision. Runs pricing formula. Generates branded PDF. Sends to customer via Resend AND to contractor for approval (configurable via env CONTRACTOR_APPROVAL_REQUIRED).
- GET /api/quote/:id → contractor-approval view (one-click approve/edit/reject), emails customer on approve.
- GET /api/quote/:id/pdf → returns the PDF directly from R2 cache.

D1: quotes (id, ts, customer_name, customer_contact, address, language, photos_r2_keys[], vision_extracted_json, pricing_json, pdf_r2_key, status, contractor_response_at, customer_received_at)

Bindings: D1 QUOTES_DB, R2 QUOTES_R2, secrets ANTHROPIC_API_KEY + RESEND_KEY + CONTRACTOR_EMAIL + CONTRACTOR_PHONE, var CONTRACTOR_APPROVAL_REQUIRED + PRICING_FORMULA_JSON.

PDF: use @cf/svg2pdf approach OR Resend's rendered-email PDF attachment. Brand: [BUSINESS LOGO URL], [BRAND COLOR], typography Inter/Fraunces.

Output complete worker.js + wrangler.jsonc additions + D1 migration + public upload form HTML.
Prompt 3 Branded PDF template builder

The HTML/CSS template that renders to PDF — a branded estimate that looks designed.

Generate an HTML/CSS PDF template for a contractor estimate from [BUSINESS NAME].

Layout (8.5x11 portrait, half-inch margins):
- Header: business logo (left, 60px tall), business name + address + license # (right). Bottom border 1px solid.
- Customer block: "Prepared for: [NAME], [ADDRESS], [DATE]." Reference number top-right.
- Scope section: header + 2-3 sentence summary, then thumbnail grid of submitted photos (4 max, 1.5x1.5).
- Pricing table: 3 columns (item / qty / price-range). Labor and materials separated. Subtotals bold. Total range with $X,XXX – $X,XXX format.
- Complications: bulleted list of "we noticed..." items.
- Disclaimer: "Estimate valid 30 days. Subject to on-site confirmation ±20%. Permits, change orders, hidden conditions billed separately."
- Footer: signature line + date + business contact.

Style: cream #FDF9F2, ink #1A1814, [BUSINESS ACCENT]. Fraunces headers, Inter body, JetBrains Mono prices. Print-optimized.

Output: complete index.html with inline <style>, ready for puppeteer / wkhtmltopdf / @cf/pdf.
Prompt 4 Real-photo cold pitch

Cold outreach where the demo IS a generated estimate of the prospect's own truck/sign/shop.

Write me a 4-sentence cold email + 2-sentence WhatsApp follow-up to [OWNER NAME] at [BUSINESS NAME].

Setup: I took a photo of [their work van OR shop sign OR a sample wall on their site] and ran it through a quote generator I built. Attached is the resulting PDF estimate (in their name, with their formula, branded for their company). It took 90 seconds end-to-end.

Email:
- Open with specific photo + 90-second timestamp ("I photographed your van outside the Hialeah Home Depot at 4:14pm. By 4:15pm…")
- Reference what the estimate priced
- Plain-text the price range from the PDF
- Name: $3k setup, $500/mo, 3 days to live
- Ask one yes/no: "want me to wire this into your existing Stripe so customers can deposit-and-confirm?"

WhatsApp: acknowledges email + offers a 15-min Loom walking through how a customer would use it on mobile.

No emojis. No "circle back." Attach the PDF. Don't describe it — let it speak.
06Selling script

Discovery question (ask this first)

"From the moment a homeowner in Coral Gables decides they want a quote from you, how long until they have a number in their hand they can act on?"

The frame

Every day a customer waits on a quote is a day your competitor is the cheaper option. A 90-second estimate arrives before the customer has Googled three other contractors. Speed-to-quote is the single best leading indicator of close rate in the trades.

The demo play

On the call: have them text you a photo of their truck or a recent job. While you talk, you submit it. Before the discovery call ends, the PDF estimate lands in their email. They see their own brand. The conversation is over at that point.

Objections

  • "Every job is different — you can't quote from a photo."

    "Right. That's why every quote is a range, not a number, and every quote ends with 'tech confirms on site.' I'm not replacing your tech — I'm replacing the 24-hour gap between phone call and quote-arrives."

  • "My customers want to talk to a human."

    "Half do. Half want a number on their phone in 5 minutes so they can call three contractors and pick. Right now that half closes with whoever responds first. This makes you that contractor."

  • "What if the AI quotes wrong?"

    "Two safeguards: every quote is a range with ±20% disclaimer, and every quote routes through you for one-click approval before it goes to the customer. Wrong-quote rate in the field is under 4%. Lost-lead rate from slow response is over 40%."

  • "$500/mo is steep for a form."

    "It's a form, a vision model, a pricing brain, a PDF generator, and a customer-facing brand piece. The closest competitor charges $1.2k/mo and you still have to write the quote yourself."

The close

"$3k now ships it in 3 days with your branding, formula, approval gate. $500/mo from the day it sends its first quote. If it doesn't shave 24 hours off your average lead-to-quote in 30 days, kill it — no contract."

07Pricing notes

Anchor on lead-to-quote time. Most trades quote in 24-72 hours; this quotes in 90 seconds. Single-job conversion improvement of 3 percentage points on a 30-job/mo pipeline pays for the full year. Per-quote cost: $0.30-0.60 in Vision tokens + R2 + Resend = under $0.65. Setup includes: photo upload form, vision integration, pricing engine, PDF template branded, contractor approval gate. Does NOT include: Stripe deposit collection ($1k), CRM sync to ServiceTitan ($2k), multi-trade routing ($1.5k). Upsell: bundle Block 02 → "estimate-to-job" pipeline at $700/mo combined.