A modern React-based rebuild of the Payment Hub EE Operations App, replacing the legacy Angular frontend. Built as part of C4GT DMP 2026 under the Mifos Initiative, targeting release 2.1.0 (October 2026).
The
mainbranch contains release code. All PRs should target thedevbranch first and will be merged tomainat release.
| Layer | Technology |
|---|---|
| Framework | React 19 + TypeScript 6 (Vite 8) |
| UI | ShadCN UI (Radix Nova) + TailwindCSS v4 |
| Routing | React Router v7 |
| Server state | TanStack Query v5 |
| HTTP client | Axios |
| Auth | Keycloak JS — ROPC (Direct Grant) flow |
| Charts | Recharts |
| PDF export | jsPDF + jspdf-autotable |
- Dashboard — operational overview with KPI stats, recent batches, recent vouchers, quick actions
- Payment Hub — Main Batches, Sub Batches, Transfers with status filters, CSV/PDF export
- Voucher Management — voucher list with status filters, bulk CSV upload
- Account Mapper — beneficiary management, create beneficiary form, self-service portal
- G2P Payment Config — configuration list and create form
- RBAC — role configuration cards and user management with lock/unlock
- Reporting Dashboard — Recharts line/bar/pie charts, KPI metrics, failed batch table, date/tenant filters
- Settings — app configuration with accordion sections
- In-app Keycloak authentication — ROPC flow, token stored in
localStorage, JWT expiry validation - Animated splash screen — shimmer progress bar, auto-navigates to login
src/
├── modules/ # Feature modules, one per domain area
│ ├── auth/ # Login page, Splash screen
│ ├── payment-hub/ # Main Batches, Sub Batches, Transfers
│ ├── vouchers/ # Voucher Management (G2P)
│ ├── account-mapper/ # Beneficiary mapping + self-service portal
│ ├── g2p-config/ # G2P Payment Configuration
│ ├── rbac/ # Role config and user management
│ ├── reporting/ # Reporting dashboard with charts
│ └── settings/ # App settings
├── components/
│ ├── ui/ # ShadCN UI primitives
│ └── shared/ # AppLayout, StatusBadge
├── lib/
│ ├── api/ # Axios client, API functions (paymentHub, accountMapper)
│ ├── keycloak/ # KeycloakProvider, useAuth hook, singleton
│ ├── exportCsv.ts # CSV download utility
│ └── exportPdf.ts # PDF download utility (jsPDF)
├── pages/ # Thin re-exports wiring modules to routes
├── config/ # Constants (APP_NAME, TENANTS, DEFAULT_TENANT)
├── main.tsx # Router setup, QueryClient, KeycloakProvider
└── index.css # Tailwind base layer and theme
root/
├── components.json # ShadCN CLI config
├── index.html # App HTML shell + favicon
├── .env.example # Environment variable template
├── .env.development # Normal dev — Gazelle real APIs (gitignored)
├── .env.g2p # G2P Config mock testing (gitignored)
└── vite.config.ts
- Node.js 18+ and npm
- Docker Desktop — for running Keycloak locally
- Access to a Mifos Gazelle backend instance (or use built-in mock data)
# 1. Clone the repository
git clone https://github.com/openMF/ph-ee-operations-web-react.git
# 2. Move into the project directory
cd ph-ee-operations-web-react
# 3. Install dependencies
npm install
# 4. Copy and configure environment variables
cp .env.example .env.development
# 5. Start the development server
npm run devNavigate to http://localhost:5173/ — the app auto-reloads on file changes.
The app supports two Vite modes, each loading its own env file, so you can switch between hitting the real Gazelle backend and testing the G2P Config module against MSW mocks without editing env vars by hand.
Loads .env.development.
cp .env.example .env.development
npm run devLoads .env.g2p. Starts MSW (VITE_ENABLE_MSW=true) to serve mocked responses for the G2P Config endpoints (/g2pPaymentConfig, /governmentEntity, /program, /dfsp) — useful when the real G2P backend at VITE_G2P_SERVICE_URL isn't deployed yet.
cp .env.example .env.g2p
# then edit .env.g2p and set VITE_ENABLE_MSW=true
npm run dev:g2pBuilding for either mode works the same way: npm run build (normal) or npm run build:g2p (G2P mocks) — see Building for Production.
Copy .env.example to .env.development (normal dev) or .env.g2p (G2P mock testing) and fill in the values — see Development Modes.
| Variable | Description |
|---|---|
VITE_API_BASE_URL |
Base URL for the Payment Hub Operations backend (/api/v1) |
VITE_BULK_CONNECTOR_URL |
URL for Bulk Import / Batch creation backend |
VITE_KEYCLOAK_URL |
Keycloak auth server URL (e.g. http://localhost:8180) |
VITE_KEYCLOAK_REALM |
Keycloak realm (e.g. paymenthub) |
VITE_KEYCLOAK_CLIENT_ID |
Keycloak client ID (e.g. opsapp) |
VITE_TENANT_ID |
Default Platform Tenant Identifier used in API calls |
VITE_G2P_SERVICE_URL |
Base URL for the G2P Payment Config backend |
VITE_ENABLE_MSW |
When true (and running in dev), starts MSW to mock the G2P Config endpoints — see G2P Config mock testing |
If you have the realm export file, start Keycloak with realm pre-loaded:
docker run -p 8180:8080 \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
-v /absolute/path/to/docs/keycloak/realm-export.json:/opt/keycloak/data/import/realm.json \
quay.io/keycloak/keycloak:latest \
start-dev --import-realmReplace /absolute/path/to/ with your local path.
This skips manual realm/client setup entirely — see docs/keycloak/README.md for what the export contains and the test user you still need to create.
Run Keycloak locally on port 8180:
docker run -p 8180:8080 \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:latest start-devThen configure at http://localhost:8180:
- Create realm:
paymenthub - Create client:
opsapp- Client authentication: OFF
- Direct access grants: ON
- Valid redirect URIs:
http://localhost:5173/* - Web origins:
http://localhost:5173
- Create a test user and set credentials
Update .env.development (or .env.g2p if using G2P mock mode):
VITE_KEYCLOAK_URL=http://localhost:8180
VITE_KEYCLOAK_REALM=paymenthub
VITE_KEYCLOAK_CLIENT_ID=opsappAdd to your hosts file (C:\Windows\System32\drivers\etc\hosts on Windows, /etc/hosts on Linux/macOS):
<VM-IP> ops.mifos.gazelle.test
<VM-IP> kibana-phee.mifos.gazelle.test
<VM-IP> zeebe-operate.mifos.gazelle.test
<VM-IP> bulk-connector.mifos.gazelle.test
Update .env.development (or .env.g2p if using G2P mock mode):
VITE_API_BASE_URL=https://ops.mifos.gazelle.test/api/v1
VITE_BULK_CONNECTOR_URL=https://bulk-connector.mifos.gazelle.test
VITE_TENANT_ID=greenbank| Route | Auth | Description |
|---|---|---|
/splash |
Public | Animated splash screen |
/login |
Public | In-app Keycloak login (ROPC) |
/ |
Protected | Dashboard — KPIs, recent batches, quick actions |
/payment-hub |
Protected | Main Batches, Sub Batches, Transfers |
/vouchers |
Protected | Voucher list, status filters, CSV upload |
/account-mapper |
Protected | Beneficiary list and create form |
/g2p-config |
Protected | G2P Payment Config list and create |
/rbac |
Protected | Role config and user management |
/reporting |
Protected | Charts, KPI metrics, failed batch table |
/settings |
Protected | App configuration |
/account-mapper/self-service |
Public | Beneficiary self-service portal (iframe) |
The self-service portal is a standalone, iframe-friendly page for beneficiaries to update their own payment details — no Keycloak credentials required.
URL format:
/account-mapper/self-service?beneficiaryId={id}
Example:
http://localhost:5173/account-mapper/self-service?beneficiaryId=9876543210
- Looks up the beneficiary via
GET /beneficiary/{id}(falls back to mock data if the API is unreachable) - Pre-fills a form with current Financial Institution, Financial Address, and Payment Modality
- On submit calls
PUT /beneficiary/{id}via TanStack QueryuseMutation - No sidebar, no header — minimal white card layout, mobile responsive, embeddable in external portals
npm run build # normal build, loads .env.production if present, else .env
npm run build:g2p # G2P mock-mode build, loads .env.g2pBuild artifacts are output to dist/.
Contributions are welcome.
- All PRs should target the
devbranch - Reference the relevant Jira ticket in your PR title:
PHEE-XXX: short description - For design references, see the Figma file (link to be added)
- For backend integration questions or access, reach out to the project mentors