Debt Manager
A full-stack shared-expense tracker in the spirit of Splitwise. A React Native mobile app with its own Express/MongoDB backend, built from scratch with a relational data model designed around group credit balances.
Developer
2023







CreditStack is a group expense tracker. Users create groups called "stacks," add members, log shared expenses, and the app tracks who is a creditor and who is a debtor within each group. It's a full-stack build: a React Native app on Expo talking to a Node.js/Express/MongoDB backend I wrote, over JWT-authenticated REST.
Group expense apps look simple, but the data model is where the real work is. Each group needs members, each member needs a running credit balance against that group, each expense needs to know who paid, and totals need to roll up into a per-user summary across all the groups someone belongs to. The schema uses three Mongoose collections: User, Stack (the group), and a Member join collection that holds the per-user-per-stack credit balance, plus an Entry collection for individual expenses. Designing Member as a join table means adding a new member or rebalancing credits is a single atomic write rather than a cascade across documents.
The backend handles authentication with bcrypt password hashing and JWT middleware on every protected route, plus email verification through nodemailer SMTP. The invitation flow is the interesting cross-channel piece: the inviter posts an invitee's email, the backend generates a per-invite link, and when the invitee opens it the backend renders a server-side EJS landing page confirming they've joined before the app picks up. Email verification uses the same server-rendered EJS pattern. On the mobile side, the JWT is persisted in AsyncStorage and validated on app open, and the app covers stack creation and joining, member management, expense entry with description/amount/date, per-stack history with expandable entries, a cross-stack summary of total credit and total debt, and a profile screen with an image picker for avatars. The visual identity was adapted from a Figma community template, re-interpreted rather than copy-pasted, using electric blue, white cards, decorative wave shapes, and a red/blue color code where debtor amounts are red and creditor amounts blue, so a user opening a stack instantly knows whether they owe or are owed. The app is built and demoed; the backend is deployed.
Modeling many-to-many group membership with per-relationship state. The credit balance isn't a property of a user or of a group, it's a property of the relationship between them. Representing that as a Member join collection (rather than embedding balances in either the user or the stack) is what makes the whole thing query cleanly and update atomically.
Rolling up balances across groups. A user's "total credit / total debt" summary has to aggregate across every stack they're in. Designing the schema so this rollup is efficient rather than requiring a full scan was a deliberate modeling decision.
A cross-channel invitation flow. Inviting someone spans the app, the backend, the user's email inbox, and a browser landing page before returning to the app. Coordinating that handoff, generating per-invite links and rendering server-side EJS landing pages meant the backend had to serve real HTML, not just JSON.