
Built for the people who fix what breaks.
Built for the people who fix what breaks.
A bilingual AI companion for residential HVAC contractors — estimate builder, diagnostic AI, callback scheduler.
The challenge
The residential trades — HVAC, plumbing, electrical — are a $500B+ industry running largely on clipboards, group texts, and spreadsheets. The software solutions that exist were designed for office workers: complex UI, English-only, cloud-dependent, and priced for enterprise procurement.
The Phoenix metro area alone has thousands of residential HVAC contractors, many of them small owner-operated businesses with bilingual teams. They need tools that work the way they work — fast, offline-capable, bilingual, and built around their actual job: diagnosing systems, writing estimates, booking callbacks.
The specific problems: estimates written in the field get lost before follow-up; crews switch between English and Spanish mid-conversation but tools don't; technicians need diagnostic guidance without slow jobsite connections; callbacks fall through without a lightweight CRM a field tech will actually use.
How we built it
Bilingual from day one: not a translation layer bolted on later. Every UI element, every AI response, every notification authored in both English and Spanish. Language toggles at the session level — a crew member can switch languages without logging out.
Mobile-first, offline-capable: technicians use phones, not laptops. Every core workflow (estimate creation, diagnostic lookup, callback scheduling) works with degraded connectivity. AI companion, not AI replacement: the AI provides reference documentation, suggests follow-up questions, and drafts estimates based on technician notes.
Stack: Next.js (PWA with service worker for offline), FastAPI backend with Spanish/English prompt templates, Supabase (auth + data with RLS for multi-tenant team accounts), Resend for transactional email, AWS S3 for invoice/estimate PDF storage. Bootstrapped pre-seed with no external capital.
System map
How the pieces talk to each other.
Selected screens
Real product surfaces from the engagement — not stock illustrations.

Dispatch board — 32 jobs today, 11 crews scheduled, regional load balanced live.
What it actually looks like
Architecture diagrams, CI runs, and dashboards from the engagement — not stock illustrations.
What shipped
Bilingual UI (EN/ES) — all copy, labels, AI responses, and notifications. AI diagnostic companion — natural-language symptom input, structured system guidance output. Estimate builder — field-input form → branded PDF → email delivery.
Callback scheduler — lightweight CRM for follow-up management. PWA with offline mode for core workflows. Beta deployment to initial Phoenix-area HVAC contractors.
Results
Beta live with initial cohort of Phoenix-area HVAC contractors. 100% bilingual coverage from first public release — no "coming soon" for Spanish. Estimate-to-callback workflow tested and validated by actual contractors.
Zero external capital required to reach beta: fully bootstrapped.
Bilingual-from-scratch is an engineering discipline, not a translation afterthought. Building it into the architecture (prompt templates, UI copy management, locale routing) from day one is significantly less work than retrofitting it. Trayd validated that small trades businesses will adopt software if it matches their actual workflow.
Talk to people on this work.
No fabricated quotes. Reference contacts are shared during discovery, with both parties' consent.
Engineering lead
Worked alongside on production trading systems for 5+ years. Available for technical reference calls — code quality, on-call discipline, incident behavior.
Founder
Engaged Sage Ideas for a Ship + Operate combination. Willing to talk about scope discipline, timeline accuracy, and what handoff actually looked like.
“The contractor opens the app on a roof in July. If it takes more than one tap to write an estimate, it doesn't get used.”
What almost happened.
Every project has near-misses. Decisions that, if we'd kept going, would have shipped a hole. The list below is the diff between the version that almost made it to prod and the version that did.
Inline excerpts.
Trimmed, but real. These are the patterns that made the system survive Stripe retries, multi-tenant queries, and a Discord bot that won't hallucinate positions.
// lib/diagnose.ts — production excerpt
const DIAGNOSTIC_SCHEMA = z.object({
likely_cause: z.string(),
next_check: z.string(),
parts_needed: z.array(z.string()),
est_time_minutes: z.number(),
language: z.enum(['en', 'es']),
})
export async function diagnose(symptoms: string, locale: 'en' | 'es') {
const res = await openai.chat.completions.create({
model: 'gpt-4o',
response_format: { type: 'json_schema', json_schema: SCHEMA },
messages: [
{ role: 'system', content: SYSTEM[locale] },
{ role: 'user', content: symptoms },
],
})
return DIAGNOSTIC_SCHEMA.parse(JSON.parse(res.choices[0].message.content!))
}