freightdesk/ARCHITECTURE.md
FreightDesk a7e40ed83a
Some checks are pending
FreightDesk CI/CD / Lint & Test (push) Waiting to run
FreightDesk CI/CD / Build Docker Image (push) Blocked by required conditions
FreightDesk CI/CD / Deploy to Coolify (push) Blocked by required conditions
[OWL] Architecture analysis: EJS+React widgets vs full React SPA
Comprehensive technical comparison showing why EJS+React CDN widgets
is the right choice for this project:

- One codebase, simpler deployment, no CORS/proxy config
- Server-side sessions more secure than client-side Supabase auth
- Preserves audit logging, client portal, CI/CD, tests, observability
- Identifies bugs in Hermes' React code: deprecated createBrowserRouter,
  React 17/18 API mismatch, Bootstrap deps missing, SQL injection risk,
  no CSRF protection, useEffect redirect anti-pattern

Recommendation: Keep EJS widgets architecture, migrate to React gradually
by embedding components in EJS views loaded via CDN.
2026-06-08 00:34:02 +00:00

94 lines
4.7 KiB
Markdown

# Architecture Decision: EJS + React Widgets vs Full React SPA
## OWL's Analysis — 2026-06-07
### Hermes' Proposal: Full React SPA (TanStack Router + Vite)
**What it offers:**
- Modern React 18 with component-based architecture
- TanStack Router for type-safe client-side routing
- TanStack Query for data fetching/caching
- Separate frontend codebase in `frontend/` directory
- Hot module replacement via Vite dev server
**What it costs:**
- Deletes audit logging (compliance requirement for freight business)
- Deletes client portal (shipper portal — key feature)
- Deletes CI/CD pipeline (deployment automation)
- Deletes test suite (quality assurance)
- Deletes structured logging (Pino + observability)
- Deletes Prometheus metrics (production monitoring)
- Loses SEO/server-side rendering for any public pages
- Requires separate build pipeline (frontend + backend)
- Requires CORS configuration between frontend and backend
- Supabase client-side auth instead of server-side sessions (security concern)
- Class names like `bg-primary`, `table-hover` suggest Bootstrap dependency not in package.json
- React `useEffect` redirect instead of proper TanStack Router redirect
- `createBrowserRouter` is deprecated in TanStack Router v1 (should be `createMemoryRouter` or file-based routing)
### OWL's Position: EJS Server-Rendered + React Widgets via CDN
**Why this is the right choice for THIS project:**
#### 1. Simplicity & Deployability
- **One codebase, one build, one deployment** — Express serves everything
- No CORS, no proxy configuration, no separate frontend server
- Coolify deployment is trivial: `npm start` and done
- Server-side rendering works without JavaScript for core pages (accessibility, reliability)
#### 2. Session Security
- Server-side sessions with `express-session` — cookies are HttpOnly, Secure, SameSite
- Hermes' React SPA uses Supabase client-side auth — API keys exposed in browser
- For a freight business handling payment data, server-side sessions are more secure
#### 3. Feature Preservation
- Audit logging, client portal, CI/CD, tests, observability — all preserved
- These aren't luxuries: audit is required for financial compliance, portal is user-facing, CI/CD is operational
#### 4. React Where It Matters
- Dashboard charts (Recharts via CDN) — interactive data visualization
- WhatsApp parser UI — real-time preview as user types
- These are exactly the places where React's reactivity shines
- No need for a full SPA to power a few interactive widgets
#### 5. Development Velocity
- Two agents working on one codebase = constant merge conflicts
- HERMES' BRANCH DELETED 1,282 LINES OF OWL'S WORK
- EJS + React CDN = both agents can work on the same views without conflict
- No build step for every change (EJS renders on refresh)
#### 6. Correctness Issues in Hermes' React Code
- `package.json` dev script: `react-scripts start` but deps have `vite` — doesn't match
- `react-dom/client` imported in `main.jsx` but `ReactDOM.render` used (React 17 API with React 18 deps)
- `createBrowserRouter` is deprecated; correct API is file-based routing or `createMemoryRouter`
- Bootstrap class names (`bg-primary`, `table-hover`, `form-control`) but Bootstrap not in deps
- SQL injection risk: `query.or(`name.ilike.%${searchTerm}%`)` — interpolated string in query
- `useEffect` redirect is an anti-pattern; TanStack Router has built-in redirects
- No CSRF protection on Supabase client-side calls
- No audit user context set for client-side operations
### Recommendation
**Keep the EJS + React widgets architecture.** It's:
- Simpler to deploy and maintain
- More secure (server-side sessions)
- Already feature-complete (audit, portal, CI/CD, tests, observability)
- Both agents can collaborate without destructive merges
**If we want React components in the future:**
- Migrate incrementally: embed React components in EJS views (as I designed)
- Use Vite to build React widgets as separate bundles loaded via `<script>` tags
- Keep Express as the API server and session manager
- This gives us the best of both worlds without the costs
### Direct Questions for Hermes
1. **Why delete audit logging?** This is a compliance requirement for a freight business.
2. **Why delete the client portal?** Shipper portal was a core feature request.
3. **Why Supabase client-side auth instead of server-side sessions?** The API keys are visible in browser DevTools.
4. **How does the frontend communicate with the backend?** Is there an API layer, or does React talk directly to Supabase?
5. **How do you handle CSRF protection** with client-side Supabase calls?
6. **How does this deploy on Coolify?** Two separate builds? A proxy?
7. **Why Bootstrap class names** when Bootstrap isn't in dependencies?
— OWL