Frontend architecture¶
Single codebase, multiple modes¶
One React/Next.js application serves all user surfaces. The application renders differently based on the authenticated user's role — determined by JWT claims at login. There is no separate admin app, no separate ops portal, no separate build.
Mode resolution¶
User authenticates → API Gateway validates JWT
→ JWT contains role claim
→ App bootstraps with RoleContext
→ Navigation, data density, actions derived from context
Role claims → mode mapping:
| JWT role | App mode | Navigation | Data scope |
|---|---|---|---|
customer |
Customer mode | Bottom tab (mobile-first) | Own data only |
agent |
Back office — agent | Sidebar — customer-focused | Customer + operational fields |
compliance |
Back office — compliance | Sidebar — compliance-focused | KYC, AML, cases |
risk |
Back office — risk | Sidebar — risk-focused | Risk dashboards, capital |
admin |
Back office — admin | Full sidebar | All data + admin functions |
Security boundary¶
Front-end permission checks are UX only, not security.
The API gateway enforces data scope server-side. A customer JWT will be rejected by the API if it attempts to call a back office endpoint — regardless of what the client-side code does. Never rely on front-end rendering logic for security.
Customer mode targets¶
- Bundle size: ≤ 500kb gzipped initial load (NFR-016)
- Time to interactive: ≤ 2 seconds on 4G (NFR-017)
- Mobile-first: designed for iOS and Android at 390px viewport
- Bottom tab navigation: max 5 destinations
Back office mode design¶
- Desktop-optimised: sidebar navigation, higher data density
- All agent actions write to immutable audit log (MOD-047) before taking effect
- Role-scoped data: API returns only what the role is permitted to see
- No destructive action without explicit confirmation and audit trail entry
Shared component library¶
Zero divergence between modes (NFR-009). All UI primitives — buttons, inputs, cards, tables, modals — are shared. Mode context determines which components render and with what props. A transaction row renders the same component in both modes — context adds extra fields and actions in back office mode.
Key design patterns¶
Mode-aware rendering:
<TransactionRow transaction={tx} mode={useRoleContext().mode} />
// customer mode: shows merchant, amount, date, category
// agent mode: adds MCC code, network ref, risk score, AML flag, actions
Gate disclosure before product acceptance:
// Disclosure gate — customer cannot accept without viewing terms
<DisclosureGate product={product} onAccepted={handleAccept}>
<ProductTermsScreen />
</DisclosureGate>
// Logs disclosure event to audit trail before enabling Accept button
Related¶
- Architectural principles — AP-001 (KISS), AP-004 (security), AP-005 (customer driven) and AP-007 (evolution) are the primary principles governing the frontend
- ADR-004 — Single frontend codebase for customer and back office
- ADR-007 — Frontend framework selection (React/Next.js + Capacitor)
- ADR-011 — CRM approach (embedded in back office)
- ADR-012 — External disclosures system (in-app gate)