projects / MVP core flows shipped
WIMM
Where is my money?
Personal finance across desktop and mobile — one NestJS API, a shared design system, and AI-assisted transaction categorization.
- NestJS
- Prisma
- PostgreSQL
- Electron
- React 19
- Expo + React Native
- Anthropic Claude SDK

Overview
WIMM is a personal finance platform that runs across desktop and mobile from a single backend. A NestJS API owns all business logic; an Electron + React 19 desktop client and an Expo + React Native mobile client consume it through shared, framework-agnostic contracts. Bank statements come in via CSV and OFX, get deduplicated and categorized — by a pattern-rules engine and by Claude — and feed reports, recurrences, and installment plans.
It exists because tracking money in a Brazilian financial life means handling things most finance apps skip: installment plans (parcelamento), mixed statement formats, and bilingual use — i18n in Portuguese and English from day one. Development started in April 2026 and is active. The MVP core flows are shipped — auth, imports, categorization, recurrences, reports, and desktop packaging — and the repository stays private while the product matures.
Live walkthrough
Native product walkthrough
iOS native build
Architecture
The monorepo is pnpm workspaces + Turborepo: three apps plus one shared package. The contribution rules are written down and enforced — backend owns logic, clients stay thin, abstract only on second duplication.
apps/api— NestJS + Prisma + PostgreSQL; JWT auth with refresh tokens, ThrottlerGuard rate limiting, class-validator DTOs, Passport strategiesapps/desktop— Electron + React 19 + Vite; React Query, Radix UI, i18next, electron-builder packagingapps/mobile— Expo + React Native; React Navigation 7, NativeWind v4, Victory Native XL charts on Skia, expo-secure-store token storagepackages/shared— framework-agnostic DTOs and API contracts
The import pipeline is the technical center: parse → normalize → dedupe (fingerprint hash) → categorize → preview → commit. Categorization combines a rules engine — system-level and user-level pattern matching — with AI categorization through the Anthropic Claude SDK. A recurrence engine materializes recurring transactions through a target date, and the data model treats InstallmentPlan, Recurrence, CategorizationRule, and ImportBatch as first-class entities rather than flags on Transaction.
Auth is where the client design earns its keep. The desktop axios interceptor implements a single-flight refresh — concurrent 401s queue behind one refresh call instead of stampeding the API — and the same flow is ported 1:1 to mobile. The design system works the same way: CSS tokens in the desktop renderer are mirrored by NativeWind v4 tokens on mobile (bg-surface-1, text-fg-muted), one vocabulary on both platforms.
Screenshots
Captured from the shipped MVP — mobile and desktop clients on the same token system.







Stack & Decisions
| Choice | Rationale |
|---|---|
| pnpm + Turborepo monorepo | Three apps and a shared package under one toolchain; monorepo discipline is a written contribution rule |
| NestJS + Prisma + PostgreSQL | Backend owns the logic; both clients stay thin consumers of one API |
| Shared DTO package | Framework-agnostic API contracts, so desktop and mobile cannot drift from the backend |
| CSS tokens ↔ React Native theme tokens | One vocabulary for the design system across Electron and React Native |
| Rules engine + Claude SDK | System- and user-level pattern rules alongside AI categorization in the import pipeline |
| Fingerprint-hash dedupe | Duplicate transactions are caught during import, before preview and commit |
| Single-flight refresh interceptor | Avoids refresh stampedes and queue race conditions; ported 1:1 from desktop to mobile |
| electron-builder | Distribution artifacts ready: macOS DMG, Windows NSIS, Linux AppImage |
Links
The repository is private. The codebase — import pipeline, recurrence engine, auth flow, and architecture docs — can be walked through end to end in an interview. Get in touch.