A
The caller card arrives before the phone rings
An unknown number calls. Before the phone starts ringing, a card lands in Telegram with who it is, their number in a tappable format, and the last project they discussed. By the time it is picked up, the context is already there.
- Recording is off by default
- Both parties are told before any recording starts
- Call history writes itself into the client card
- A call can never move a project on its own
Ref · sauna-crm · app/api/twilio/voice/route.ts
B
Estimates and contracts sign themselves off
The client opens a link, reads the estimate, and signs on their phone. The signature page is composited into the real PDF along with both names, the date, and the audit trail. Branding comes from the company record, so the document looks like the contractor's, not like ours.
- Built in-house, no DocuSign
- IP and user agent recorded
- Links expire; requests can be voided
- Estimate, contract, certificate of completion
Ref · sauna-crm · supabase/migrations/028_esignature.sql
C
Deposits by card and by bank transfer
Built on Stripe Connect so the money lands in the contractor's own account. The platform fee comes out of their payout rather than being added to the homeowner's total, and bank transfer is offered because on a large deposit the card fee is the difference between five dollars and a few hundred.
- Their Stripe account, their money
- Card and ACH
- Fees computed in whole cents
- Refunds return the fee proportionally
Ref · sauna-crm · lib/deposit-fee.ts
D
A bot that only takes buttons
The crew moves a project forward by tapping a button in Telegram: deposit received, scheduled, work started, finished, paid. It refuses free text and voice notes on purpose, because one misheard word would move a real project.
- Only the legal next step is offered
- Installers can move work, not documents
- Roles mirror the database rules
- No free text, no voice
Ref · sauna-crm · lib/telegram-actions.ts
E
Quiet estimates get chased, but not by a robot
When an estimate goes quiet, the system drafts the nudge and shows it. Nothing is sent until it is read and sent deliberately. It waits business days, stops after three attempts, and is not allowed to invent a number that is not already on the estimate.
- Drafts, then a second deliberate tap
- Waits 3, 7, then 14 business days
- Stops at three; weekends skipped
- Writes in the owner's voice, not a marketer's
Ref · sauna-crm · lib/followup-draft.ts
F
The rest of the working day
Reports that agree with each other because revenue is defined in one module. Crew payouts under one rule instead of three that disagreed. Stock that comes off the shelf when a client approves, once, even if the webhook fires twice. A calendar where an installer sees their own jobs.
- Reports, revenue, profit
- Crew payouts
- Inventory and stock deduction
- Calendar and client portal
Ref · sauna-crm · lib/revenue.ts, lib/installer-pay.ts