Demonstration workspace — every record is sample data. Mock connectors only; no live DMS or Google account is connected.

Architecture Notes

An honest map of this build: what works today, what is simulated, and exactly what production needs.

What is real in this build

  • Typed domain model covering vehicles, purchases, customers, deals, loans, leases, rentals, fleet, service, payments, documents, communications, sync and audit.
  • Working finance math: amortization, payment derivation, payoff quotes, aging buckets, true cost and projected gross.
  • Full CRUD across the admin app with an audit entry written on every change, persisted in the browser.
  • Search, filters, sorting, detail pages, forms, validation, CSV exports and file import previews.

What is simulated

  • DMS, Google Sheets and Google Forms connectors are mock adapters — no external system is contacted.
  • CSV / XLSX / PDF parsing returns a deterministic preview; production needs a server-side parser and OCR service.
  • Messages are logged, never actually sent; payments are recorded, never actually processed.
  • There is no login yet: the app assumes a single signed-in operator, with roles modeled but not enforced.

Layers

Routes (TanStack Start)
  /            public marketing site
  /app/*       admin shell + operational modules

UI layer
  components/brand      logo + lockups
  components/app        PageHeader, KpiCard, DataTable, StatusBadge, QuickAdd, GlobalSearch
  components/ui         shadcn primitives

Domain layer
  domain/types.ts       entities + unions (the contract)
  domain/finance.ts     amortization, payoff, aging, affordability

Data layer
  data/seed.ts          two locations, 18 vehicles, 12 customers + related records
  data/store.tsx        React context, CRUD, audit log, localStorage persistence
  data/selectors.ts     derived KPIs and cross-entity queries

Integration layer
  integrations/adapters.ts   SyncAdapter / FileImportAdapter interfaces + mock implementations

Path to production

  1. Database & auth. Replace the in-browser store with a hosted Postgres schema mirroring domain/types.ts, add sign-in, and enforce the roles already modeled in Admin with row-level policies per location.
  2. Server functions. Move finance math, funding, payment posting and exports into server functions so amounts cannot be manipulated client-side.
  3. Real connectors. Implement SyncAdapter against the dealer DMS and Google APIs; keep the human conflict-review step exactly as built.
  4. Payments. Add a card/ACH processor behind the existing payment posting flow, with reversal and receipt records preserved.
  5. Messaging. Attach an SMS and email provider to the communications module; consent checks are already enforced in the UI.
  6. Documents. Add file storage plus e-signature; the checklist, expiration and title-exception logic already exists.

Decisions and tradeoffs

  • State lives in one typed store rather than scattered component state, so the future database swap touches one file.
  • Money math lives in the domain layer, never in components, so the same numbers appear on every screen.
  • Sync never auto-overwrites the dealer's books — a person resolves every conflict and the resolution is logged.
  • Affordability output is explicitly framed as decision support, not a credit decision or legal advice.