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
- 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. - Server functions. Move finance math, funding, payment posting and exports into server functions so amounts cannot be manipulated client-side.
- Real connectors. Implement
SyncAdapteragainst the dealer DMS and Google APIs; keep the human conflict-review step exactly as built. - Payments. Add a card/ACH processor behind the existing payment posting flow, with reversal and receipt records preserved.
- Messaging. Attach an SMS and email provider to the communications module; consent checks are already enforced in the UI.
- 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.