Stack

LayerTechnology
FrontendReact 18 + TypeScript (Vite 5) — Cloudflare Pages
Backend APICloudflare Worker (TypeScript) — env: bernies
DatabaseCloudflare D1 — lawncare_db (ID: f029e545-6c71-4762-8776-fd4f930264df)
AuthPBKDF2-SHA256 password hash in D1, HMAC-signed JWT (24hr expiry)
MobilePosition:fixed sidebar drawer + hamburger button (mobile-first)

Database Tables

TableKey Columns
admin_usersid (UUID), email, password_hash
clientsid, name, email, phone, service_address, city, zip, status, notes
jobsid, client_id, service_type, scheduled_date, scheduled_time, duration_minutes, address, price_cents, status, recurrence, notes
estimatesid, estimate_number, client_id, services, total_cents, status, valid_until, notes
invoicesid, invoice_number, client_id, job_id, amount_cents, description, status, issue_date, paid_date
invoice_itemsid, invoice_id, description, quantity, unit_price_cents, total_cents
paymentsid, invoice_id, amount_cents, method, paid_date, notes
notesid, entity_type, entity_id, content, created_at
settingskey, value — business_name, service_types, invoice_footer, invoice/estimate counters

File Structure

lawncare-portal/
  src/
    App.tsx                     ← Root — token check → PublicSite or AdminApp
    api.ts                      ← All fetch() calls — VITE_API_URL base
    index.css                   ← Mobile-first CSS (sidebar drawer, hamburger, stat grid)
    main.tsx                    ← Vite entry
    context/AppContext.tsx       ← Global state — auth, all data, config; sets document.title
    components/
      PublicSite.tsx             ← Config-driven public landing page + estimate form
      AdminApp.tsx               ← Sidebar drawer + hamburger shell
      admin/
        Dashboard.tsx            ← Stats + recent jobs panel
        JobsView.tsx             ← Job CRUD + modal form
        ClientsView.tsx          ← Client CRUD + job history
        EstimatesView.tsx        ← Estimate CRUD + convert to invoice
        InvoicesView.tsx         ← Invoice CRUD + print view
        CalendarView.tsx         ← Month/week calendar
        ReportsView.tsx          ← Revenue charts + KPIs
        SettingsView.tsx         ← Business settings + password change
  worker/index.ts               ← Worker API (all routes)
  migrations/
    0001_init.sql               ← Full schema
    0002_settings_seed.sql      ← Bernie's Backyard defaults + admin hash
  wrangler.toml                 ← bernies env + D1 binding + custom domain

Key API Routes

MethodRouteAuth
GET/api/configNone — public settings for public site
POST/api/requestsNone — estimate request from public form
POST/api/auth/loginNone — returns JWT
GET/POST/PUT/DELETE/api/jobs/*JWT — job CRUD
GET/POST/PUT/DELETE/api/clients/*JWT — client CRUD
GET/POST/PUT/DELETE/api/estimates/*JWT — estimate CRUD
GET/POST/PUT/DELETE/api/invoices/*JWT — invoice CRUD + line items
GET/PUT/api/settingsJWT — business settings