Stack
| Layer | Technology |
|---|---|
| Frontend | React 18 + TypeScript (Vite 5) — Cloudflare Pages (Ice Blue #3B82F6 theme) |
| Backend API | Cloudflare Worker (TypeScript) — env: procomfort |
| Database | Cloudflare D1 — hvac_db (ID: 4d63378c-fad7-4e9c-bc05-14d9dce00bf8) |
| Auth | PBKDF2-SHA256 password hash in D1, HMAC-signed JWT |
Database Tables
| Table | Key Columns |
|---|---|
| admin_users | id (AUTOINCREMENT), email, password_hash, full_name |
| clients | id, name, email, phone, address, city, zip, property_type (Residential/Commercial/Industrial), status, notes, job_count |
| jobs | id, client_id, service_type, scheduled_date, scheduled_time, duration_minutes, address, price_cents, status, priority (Normal/High/Emergency), technician_notes, recurrence |
| maintenance_plans | id, client_id, plan_type (Annual/Bi-Annual/Quarterly/Monthly), price_cents, status (Active/Expired/Pending/Cancelled), start_date, next_service_date, notes |
| estimates | id, estimate_number, client_id, services, total_cents, status, valid_until, notes |
| invoices | id, invoice_number, job_id, client_id, amount_cents, description, status, issue_date, paid_date |
| service_requests | id, name, email, phone, address, service_type, urgency, description, status (New/Reviewed/Scheduled/Resolved), admin_notes |
| settings | key, value — business_name, service_types, emergency_phone, invoice/estimate counters |
File Structure
hvac-portal/
src/
App.tsx / api.ts / index.css / main.tsx
context/AppContext.tsx
components/
PublicSite.tsx ← Emergency CTA + service types + request form
AdminApp.tsx ← Mobile-first sidebar + hamburger
admin/
Dashboard.tsx / JobsView.tsx / MaintenancePlansView.tsx
ClientsView.tsx / EstimatesView.tsx / InvoicesView.tsx
CalendarView.tsx / ServiceRequestsView.tsx
ReportsView.tsx / SettingsView.tsx
worker/index.ts
migrations/0001_init.sql / 0002_settings_seed.sql (ProComfort defaults)
wrangler.toml ← procomfort env + D1 binding + custom domain