End-to-end loop
Roof to receipt

How it works

The Spanwright desk — from the first inbound to the final payment.

An inquiry lands 24/7 and the desk scores it. A walkthrough is booked from a single calendar. The lead converts to a project, permits pull through five statuses, subs coordinate against the critical path, the homeowner gets a daily photo digest, change orders ship priced and approved, the invoice emails with a Stripe checkout link, and a side-by-cron sweep chases aging buckets.

Every step below mirrors a screen that already runs in production — the homeowner’s experience compresses from “where are we on my remodel” to one inbox tab and one Stripe checkout.

The ten steps

Roof to receipt, in order
A static overview of the loop — open the desk at the bottom of the page.
  1. 01Inbound inquiry lands 24/7jump
  2. 02Lead qualification scores itjump
  3. 03Walkthrough auto-scheduledjump
  4. 04Project is converted from the leadjump
  5. 05Permits pulled with the right jurisdictionjump
  6. 06Subs coordinate against the critical pathjump
  7. 07Daily photo updates auto-email the homeownerjump
  8. 08Change orders surfaced and pricedjump
  9. 09Invoice issued and emailedjump
  10. 10Payment chased across aging bucketsjump
01

Inbound inquiry lands 24/7

A real inquiry, scored the moment it lands — day, night, or weekend.

Try the intake →
Intake · Live
What the desk does
One sentence per row of how this step ships on the live desk.
  • 01.1 Public LeadIntakeForm posts to /api/inquiries — name, contact, address, scope.
  • 01.2 No bot, no scheduler tab — replies go out fast, from a real human inbox.
  • 01.3 Same email channel the homeowner is watching: spanwright-2@polsia.app.
  • 01.4 A new Inquiry row drops in the desk the second the form submits.
02

Lead qualification scores it

Three flags — project type, budget, timeline — collapse into one verdict.

See pricing →
Verdict · Qualified
What the desk does
One sentence per row of how this step ships on the live desk.
  • 02.1 Flags are computed by the Polsia AI scorer — pass / fail / unknown per dimension.
  • 02.2 Any fail → Disqualified; all pass → Qualified; ambiguous → Needs review.
  • 02.3 Contractor can override any flag inline from the qualification card.
  • 02.4 The verdict banner and the lead-row chip read from the same ladder — never drift.
03

Walkthrough auto-scheduled

A month of onsite visits, booked and managed from a single calendar.

See pricing →
Status · Scheduled
What the desk does
One sentence per row of how this step ships on the live desk.
  • 03.1 Month grid with per-day count dots — click a day to see + manage that day.
  • 03.2 Booking card captures name, phone, email, address, datetime, duration, notes.
  • 03.3 Status inline moves: Scheduled → Completed, or Scheduled → Canceled (reopens too).
  • 03.4 POSTs to /api/desk/walkthroughs; data scoped per contractor on the server.
04

Project is converted from the lead

The qualified inquiry becomes a project — once, idempotently.

See pricing →
Convert · 201
What the desk does
One sentence per row of how this step ships on the live desk.
  • 04.1 POST /api/inquiries/[id]/convert returns 201 with the new projectId.
  • 04.2 Idempotent — a second convert against an already-converted lead returns 409.
  • 04.3 Admin-only on the server (403 for non-admin callers, no information leak).
  • 04.4 Wrong-team lead lookups return 404 — they learn nothing from probing IDs.
05

Permits pulled with the right jurisdiction

Per-project permit log that walks the filing through five statuses.

See pricing →
Permit · Issued
What the desk does
One sentence per row of how this step ships on the live desk.
  • 05.1 Permit types: Building, Electrical, Plumbing, Mechanical — per-jurisdiction filings.
  • 05.2 Status ladder: Drafting → Submitted → Under Review → Approved → Issued.
  • 05.3 The first move to Issued stamps an immutable approvalDate on the row.
  • 05.4 Inspector notes are inline-editable and audit-stamped with the actor who set them.
06

Subs coordinate against the critical path

Every sub, every status, slotted today / this week / upcoming / past.

See pricing →
Bucket · Today
What the desk does
One sentence per row of how this step ships on the live desk.
  • 06.1 Sub roster per project: electrician, plumber, tile installer, HVAC, roofer, etc.
  • 06.2 Status inline flips: Scheduled → On site → Complete — No-Show surfaced distinctly.
  • 06.3 Optional assignee on each schedule row ties the sub to the critical-path line.
  • 06.4 Today / This week / Upcoming / Past buckets auto-recompute on the schedule view.
07

Daily photo updates auto-email the homeowner

A status note + up to 20 photos lands in the homeowner's inbox on save.

See pricing →
Photos · up to 20
What the desk does
One sentence per row of how this step ships on the live desk.
  • 07.1 Writer posts a body; photos upload to /api/uploads/r2 and ride along.
  • 07.2 Cap of 20 photos per update — validated client-side, server-side rejects the rest.
  • 07.3 "Notify homeowner" opt-in fires the share-portal email through the Polsia mail proxy.
  • 07.4 Homeowner lands on a public share portal under /(custom)/share/[token] — no login.
08

Change orders surfaced and priced

Drafts from the field, priced against the live estimate, approved in-app.

See pricing →
Status · Approved
What the desk does
One sentence per row of how this step ships on the live desk.
  • 08.1 Status ladder: Draft → Sent → Approved → Declined (with Decline-reason capture).
  • 08.2 priceUsd quoted vs estimatedAdditionalUsd computed against the running estimate.
  • 08.3 Approved delta rolls into project budget and appends a matching invoice line.
  • 08.4 Pending-sent backlog is the KPI a contractor wants before the homeowner calls.
09

Invoice issued and emailed

Generate, send, and collect — without a second bookkeeping tab open.

See pricing →
Invoice · Sent
What the desk does
One sentence per row of how this step ships on the live desk.
  • 09.1 InvoiceForm posts to /api/invoices — line items roll up the change-order contributions.
  • 09.2 Amount feeds Stripe hosted checkout through the installed stripe-billing module.
  • 09.3 Homeowner receives a pay email with the secure hosted Stripe link.
  • 09.4 Detail / pay / status-poll islands live under /(custom)/invoices — no embedded card forms.
10

Payment chased across aging buckets

A side-by-cron sweep emits the right reminder at the right day boundary.

See pricing →
Bucket · 1_to_30
What the desk does
One sentence per row of how this step ships on the live desk.
  • 10.1 Buckets: Current, 1_to_30, 31_to_60, 61_to_90, 90_plus — pure derivation on the row.
  • 10.2 jobs/chase-overdue-invoices.js hits /api/desk/invoices/chase-sweep-cron with x-cron-secret.
  • 10.3 Route refuses every caller when INVOICE_CHASE_SECRET is unset — never opens the world.
  • 10.4 Per-invoice lastChasedBucket is the dedupe key — idempotent across runs.

Get started

Run the whole loop on a real job.

Sign up and the desk opens in under a minute — the same screens above backing every step. Pick a tier when the workload proves it pays; the trial costs nothing until you do.

Inbound intake still routes through spanwright-2@polsia.app — same channel the desk already reads.