Roofing
RoofWorks
From website enquiry to signed proposal, without the paperwork.
A roofing contractor's whole front office: homeowners request an estimate from the website, the crew triages requests, and proposals go out as a branded PDF and a link the customer can accept online.
- Next.js 16
- TypeScript
- Supabase
- PostgreSQL
- Row-level security
- Private file storage
- React PDF
- Resend
- Enquiry to proposal
- 1 system
- Proposal delivery
- PDF + link
- Access control
- Database-level
no rekeying between tools
accepted online, timestamped
row-level security, not UI-only
What was going wrong
Estimate requests arrived by phone, text and a web form that emailed a single inbox. Nobody could say which ones had been answered. Proposals were built in a spreadsheet, exported by hand, and chased by phone — so the slow ones were the ones that got forgotten.
What we built
One system that owns the whole path. The website form writes straight into the database with the photos attached. Every request has a status and an owner, so the board tells you what is waiting on you. Proposals are assembled from priced line items and delivered two ways at once: a PDF for the customer's records, and a link they can accept from their phone. Access is enforced in Postgres with row-level security, so a crew member cannot read another crew's jobs even if the interface has a bug.
What it looks like
The screens this build was designed around.
The morning board
What is waiting on you, in the order it needs attention. Counts by status, newest requests, proposals sitting unanswered.
New requests
7
3 today
Awaiting quote
12
2 over 5 days
Proposals out
9
$104,300 pending
Accepted this month
6
up from 4
Requests by status
Newest requests
View all| Address | Job | Status |
|---|---|---|
| 114 Kathleen St | Full replacement | New |
| 87 Regent St | Leak repair | Scheduled |
| 2201 Long Lake Rd | Inspection | Quoted |
| 45 Elm St W | Shingle repair | Accepted |
Proposal builder
Priced line items, tax and totals computed as you type. The same data drives the PDF and the customer's accept page.
Line items
PR-1042| Item | Qty | Rate | Amount |
|---|---|---|---|
| Tear-off, 2 layers | 28 sq | $95 | $2,660 |
| Architectural shingles | 28 sq | $310 | $8,680 |
| Ice & water shield | 6 roll | $118 | $708 |
| Ridge vent | 42 ft | $14 | $588 |
| Disposal | 1 | $640 | $640 |
- Subtotal
- $13,276
- HST (13%)
- $1,725.88
- Total
- $15,001.88
Delivery
- Branded PDFReady
- Hosted linkNot sent
- CustomerM. Tremblay
Once sent, the customer can
- Read it on a phone, no login
- Accept or decline in one tap
- Download the same PDF you see
What it does
Public intake form
Addresses, roof details and photos, straight into the database with nothing rekeyed.
Triage board
Every request has a status and an owner, so the board tells you what is waiting on you.
Role-based access
Admins see everything; crew see their own jobs and nothing else.
Line-item proposal builder
Priced items with tax and totals computed as you type.
Branded PDF
Generated on the server, so it is identical every time it is made.
Accept online
A hosted link the customer signs off from their phone, timestamped.
Who reaches for it, and when
The owner, first thing
Opens the board and sees the three requests nobody has answered and the proposal that has been sitting unopened for a week.
A crew lead on site
Pulls up the job, the photos the homeowner sent, and the measurements taken at the estimate.
The homeowner
Gets a PDF for their records and a link they can accept without printing, signing or scanning anything.
What makes this one different
Permissions live in the database
Row-level security means a crew member cannot read another crew's jobs even if a page has a bug in it. The interface checks are only there to avoid showing buttons that would fail.
One document, two deliveries
The PDF and the customer's accept page are rendered from the same priced line items, so the paperwork and the web page can never disagree about the price.
Photos arrive with the enquiry
The intake form uploads straight to storage, which is what removes the phone call that used to start every estimate.
Built with
What each piece is doing here — the people who read this section are usually the ones who would have to maintain it after us.
Next.js 16
The application framework. Pages render on the server by default.
TypeScript
Strict mode everywhere. A field renamed in one place fails to compile in the others.
Supabase
Postgres, authentication, file storage and realtime in one managed service.
PostgreSQL
The database. Constraints and permissions live here, not in the interface.
Row-level security
Who can read which row is decided by Postgres. A UI bug cannot leak data.
Private file storage
Photos and receipts behind signed URLs, namespaced so policies can check them.
React PDF
Documents generated on the server, identical every time they are made.
Resend
Transactional email — invitations, reminders and sign-in links.
Want something like RoofWorks?
It does not have to be your industry — the underlying problem is nearly always the same. Tell us how the work moves through your business and we will tell you what it would take.
Every project is quoted on its own. Turnaround starts at two weeks.