Munny
Personal finance dashboard with Plaid sync. Answers "can I afford this?"
- React
- TypeScript
- Node.js
- Express
- MongoDB
Budgeting tools tell you what you already spent. Munny tells you whether a purchase fits in the rest of the month, accounting for pending transactions, scheduled recurring charges, and savings goals.
Plaid sync
node-cron runs nightly. For each linked account, fetch the latest 30 days of transactions, dedupe by Plaid transaction ID, and reconcile pending-to-settled transitions. Pending charges are stored with a tentative flag so they show on the dashboard but don't double-count once they settle.
Decision endpoint
Takes (amount, category, accountId). Simulates the rest of the month forward:
- Apply the candidate purchase
- Subtract scheduled recurring charges through end-of-month
- Subtract savings-goal contributions still owed
- Return the first constraint that breaks — category cap, savings target, projected end balance — or
null
Response is { ok, brokenBy, projection }. The UI uses brokenBy to explain why a no is a no, which turns out to matter more than the yes/no itself.
Recurring-charge ownership
A recurring charge has to be assigned to a specific account or the projection lies. The naive "whatever account it last hit" fails when you rotate cards. Munny uses a weighted-recency heuristic on the last few occurrences, plus a manual override. Still gets it wrong sometimes; that's why the override exists.
Stack
Vite + React + React Query + Auth0 on the client. Express + Mongoose on the API. Zod schemas shared between them. API on Fly.io, SPA on Cloudflare Pages, MongoDB Atlas.