Borrower Portal Overview
The borrower portal is a standalone React SPA providing self-service loan management for borrowers. It runs independently from the admin dashboard with its own routing, state management, and API layer.
Tech Stack
| Technology |
Purpose |
| React 18 |
UI framework |
| TypeScript |
Type safety |
| MUI 5 |
Component library |
| React Query (TanStack Query 5) |
Server state management |
| react-hook-form |
Form handling |
| React Router 6 |
Client-side routing |
| Vite |
Build tool and dev server |
| Vitest |
Test runner |
Key Differences from Admin Dashboard
| Aspect |
Admin Dashboard |
Borrower Portal |
| Framework |
react-admin |
Plain React + MUI |
| Data fetching |
react-admin data provider |
React Query hooks |
| Auth |
react-admin auth provider |
Custom AuthContext |
| Routing |
react-admin resource routing |
React Router |
| State |
react-admin store |
React Query cache |
| Users |
Staff (viewer, officer, admin) |
Borrowers |
| Data scope |
All tenant data |
Authenticated borrower's data only |
| Port |
5173 |
5174 |
Development Setup
cd frontend/borrower
npm install
npm run dev # Vite dev server at http://localhost:5174
Other commands:
npm run build # TypeScript check + Vite build
npm run test # Vitest
npm run lint # ESLint (strict, max-warnings 0)
Feature Summary
| Feature |
Description |
| Dashboard |
Loan summaries, upcoming payments, alerts, total balance |
| Loan Detail |
Balance, payment info, amortization schedule |
| Payments |
Submit payments, preview allocation, payment history |
| Autopay |
Enroll, cancel, re-enable automatic payments |
| Payment Methods |
Add/remove bank accounts and cards |
| Documents |
View statements, download files, upload documents |
| Support |
Create support cases, message threads |
| Hardship |
Multi-step hardship application wizard |
| Profile |
Update contact info, communication preferences |
Application Structure
frontend/borrower/src/
├── App.tsx # Routes + QueryClient + AuthProvider + ThemeProvider
├── main.tsx # Entry point
├── api/
│ ├── client.ts # apiFetch(), CSRF handling, ApiHttpError
│ ├── auth.ts # login(), logout(), getMe(), getSession()
│ └── portal.ts # 41 portal API functions
├── contexts/
│ └── AuthContext.tsx # Auth state (borrower, login, logout)
├── hooks/ # React Query hooks (9 files)
├── pages/ # 17 page components
├── components/ # 25+ shared components
├── layouts/
│ ├── AuthLayout.tsx # Centered card (login, reset)
│ └── PortalLayout.tsx # AppBar + sidebar + main content
├── utils/
│ └── format.ts # humanize(), formatMoney(), STATUS_COLORS
├── types.ts # TypeScript interfaces
└── test-utils.tsx # renderWithProviders()
See Also