Stack

LayerTechnology
FrontendReact 18 + TypeScript (Vite 5) — Cloudflare Pages (Ice Blue #3B82F6 theme)
Backend APICloudflare Worker (TypeScript) — env: procomfort
DatabaseCloudflare D1 — hvac_db (ID: 4d63378c-fad7-4e9c-bc05-14d9dce00bf8)
AuthPBKDF2-SHA256 password hash in D1, HMAC-signed JWT

Database Tables

TableKey Columns
admin_usersid (AUTOINCREMENT), email, password_hash, full_name
clientsid, name, email, phone, address, city, zip, property_type (Residential/Commercial/Industrial), status, notes, job_count
jobsid, client_id, service_type, scheduled_date, scheduled_time, duration_minutes, address, price_cents, status, priority (Normal/High/Emergency), technician_notes, recurrence
maintenance_plansid, client_id, plan_type (Annual/Bi-Annual/Quarterly/Monthly), price_cents, status (Active/Expired/Pending/Cancelled), start_date, next_service_date, notes
estimatesid, estimate_number, client_id, services, total_cents, status, valid_until, notes
invoicesid, invoice_number, job_id, client_id, amount_cents, description, status, issue_date, paid_date
service_requestsid, name, email, phone, address, service_type, urgency, description, status (New/Reviewed/Scheduled/Resolved), admin_notes
settingskey, 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