A frontend-only client onboarding CRM for a Swiss financial-services setting. It gives relationship managers and compliance reviewers a secure browser workspace for registering prospective clients, collecting onboarding information, reviewing document metadata, assessing risk, tracking decisions, and inspecting audit history.
Live production: alpine-clientflow.vercel.app
The application stores its workspace data in the browser. It has no hosted backend, external data transfer, file upload, or third-party client data.
- Passwordless selection of Relationship Manager, Compliance Reviewer, or Administrator roles
- Permission checks at routes and mutation boundaries, not only hidden controls
- Decision-oriented dashboard with onboarding metrics, stage distribution, attention items, and activity
- TanStack Table client register with sorting, pagination, filters, URL synchronisation, and responsive mobile cards
- Six-step React Hook Form and Zod onboarding workflow with per-step validation, focus placement, IndexedDB draft recovery, unload warning, and confirmation
- Client detail tabs with validated role-aware editing and optimistic rollback
- Compliance queue with risk, waiting-time, and reviewer filters plus approve, request-changes, and reject decisions
- Auditable mutation history with browser-generated, translated, UTF-8 CSV export
- English/French preferences, light/dark themes, table density, reduced motion, and administrator-only deterministic reset
- Global client search with ⌘ K / Ctrl K
- MSW latency and deterministic forced-error mode for failure testing
| Responsive client register | Compliance decision |
|---|---|
![]() |
![]() |
| Mobile review queue | Mobile activity trail |
|---|---|
![]() |
![]() |
| Role | Capabilities |
|---|---|
| Relationship Manager | View dashboard and clients, create onboarding records, edit client contact data, save drafts, submit for review |
| Compliance Reviewer | View client data and audit history, work the review queue, approve, request changes, or reject |
| Administrator | Access every product area, update preferences, decide reviews, and reset deterministic workspace data |
Permissions are checked again before sensitive mutations. A disallowed route redirects safely, and a direct mutation attempt is rejected.
- Vite 8, React 19, strict TypeScript
- Tailwind CSS 4 through the official Vite plugin, with application-specific design tokens in CSS
- Source Sans 3 Variable, bundled locally through Fontsource with no remote font request
- React Router 7 with browser history and route-level lazy loading
- TanStack Query and TanStack Table
- React Hook Form and Zod
- Zustand for the selected workspace role and small UI preferences
- Recharts, date-fns, and Lucide React
- Mock Service Worker 2 and IndexedDB through
idb - react-i18next
- Vitest, React Testing Library, Playwright, and axe-core
- ESLint flat config and Prettier
Requirements: Node.js 22+ and npm 10+.
git clone https://github.com/DevRumiTech/alpine-clientflow.git
cd alpine-clientflow
npm install
npm run devNo environment variables, API keys, credentials, accounts, or paid services are required.
| Command | Purpose |
|---|---|
npm run dev |
Start the Vite development server |
npm run build |
Type-check and create the production bundle |
npm run preview |
Serve the production bundle locally |
npm run lint |
Run strict ESLint checks |
npm run format |
Format supported files |
npm run format:check |
Verify formatting |
npm run typecheck |
Run the strict TypeScript project build |
npm run test |
Run unit and integration tests once |
npm run test:watch |
Run Vitest interactively |
npm run test:e2e |
Run Playwright desktop and mobile browser tests |
npm run verify |
Run lint, formatting, types, unit/integration tests, and build |
Install Playwright Chromium once before the browser suite when needed:
npx playwright install chromiumThe UI calls a typed fetch client. MSW intercepts /api/*, applies deterministic latency or failure behaviour, validates important payloads, and delegates reads and writes to an IndexedDB repository. TanStack Query owns request-backed state and cache invalidation. Form state, URL filters, local UI state, and persisted preferences each have one explicit owner.
See architecture.md for the data-flow diagram, state boundaries, permissions, and test strategy.
IndexedDB stores clients, reviews, activity events, seed metadata, and an optional unfinished onboarding draft. localStorage is limited to the selected workspace role and UI preferences. A versioned pre-render migration maps older stored role records to the current canonical workspace identities. Reset replaces IndexedDB content with the stable 30-client seed while preserving the selected user and preferences.
The browser mock API implements:
POST /api/session, DELETE /api/session, GET /api/dashboard, GET /api/clients, GET /api/clients/:clientId, POST /api/clients, PATCH /api/clients/:clientId, GET /api/reviews, PATCH /api/reviews/:reviewId, GET /api/activity, and POST /api/reset.
The automated suite covers schemas, form errors, filters, URL state, table pending/empty/result/failure states, permissions, IndexedDB seeding/reset, legacy session migration, client creation, review updates, forced failures, CSV escaping, unsaved-change warnings, language switching, and optimistic rollback.
Playwright covers role login, no-flash migration of an older signed-in session, client filtering, new-client submission, review approval, recoverable API failure, direct SPA routes, preview smoke, and axe analysis on the dashboard in both desktop and mobile projects. Documentation captures explicitly cover 375×812, 768×1024, and 1440×900.
Local Lighthouse against the production-preview login route scored 100 Accessibility, 100 Best Practices, and 91 SEO on 30 July 2026.
The application targets WCAG 2.2 AA where applicable. It includes semantic landmarks, a skip link, one page heading, associated labels and errors, visible focus, keyboard-accessible navigation and actions, focus placement after invalid form submission, modal focus entry and Escape handling, text in addition to status colour, table captions and scoped headings, an accessible chart summary, live toast announcements, 16px mobile inputs, and reduced-motion support.
The persistent desktop sidebar becomes a drawer below 800px. Filters reflow, forms collapse to one column, dialogs become bottom panels, and the client register becomes readable row cards on narrow screens instead of shrinking the full table. There is no intentional page-level horizontal scrolling.
- Tailwind CSS 4 uses
@tailwindcss/viteand@import "tailwindcss"; the oldertailwind.config.jsplus PostCSS setup is not required here. - Vite 8’s current React TypeScript scaffold includes Oxlint by default. This project uses ESLint 9 flat config because the brief requires ESLint and the current
eslint-plugin-jsx-a11ypeer range is compatible with ESLint 9. - React Router 7 retains the declarative
BrowserRouter,Routes, andRouteAPIs used by this browser-only SPA.
This portfolio project uses synthetic people, organisations, documents, identifiers, and financial values. It is not a real KYC, AML, compliance, legal, banking, investment, or financial-services system.
- Local role selection, authorisation checks, and audit immutability are not security boundaries.
- The API worker and IndexedDB repository are intentionally client-side; concurrent users and cross-device synchronisation do not exist.
- Document entries are metadata only. No real documents are selected, read, stored, or transmitted.
- French navigation and shared control text are translated; the longer domain content remains primarily English for the portfolio scope.
- The dashboard bundle includes Recharts and MSW, so a production backend version would benefit from further bundle splitting and removal of the browser mock layer.
- As of 30 July 2026,
npm audit --omit=devreports the React Router RSC action advisory GHSA-qwww-vcr4-c8h2 in current 7.18.2. This frontend-only SPA does not use React Server Components, server actions, or a server runtime; the registry does not yet offer the advisory-listed 8.3 fix.
The deeper product and engineering narrative is in case-study.md.
Built by DevRumiTech.





