For the last few weeks I've been building TinyDebt, a tiny app for tracking debts, loans, and repayments. I wanted to share some of the technical decisions behind it, in case it's helpful to anyone building small, focused apps.
🧩 Why I built it
I kept forgetting small debts between friends, and the existing apps felt heavy: sign-ups, ads everywhere, complex finance features.
I wanted something that:
- opens instantly
- lets you add a debt in 3–5 seconds
- works offline
- stays simple forever
So TinyDebt was born.
⚙️ Tech stack
TinyDebt is intentionally lightweight:
- React Native (Expo) for mobile
- Local-first approach with AsyncStorage
- No backend - data lives on the device (only Firebase for backups)
- TypeScript everywhere
- Minimal UI with custom components instead of UI libraries
- App Store and Google Play packaging via EAS build
No user accounts, no analytics, no external dependencies except essentials.
🗂️ Data model
Every debt entry looks like:
type Debt = {
id: string;
name: string;
amount: number;
type: "owed" | "borrowed";
createdAt: number;
history: Repayment[];
};
type Repayment = {
amount: number;
date: number;
};Keeping everything serializable makes storage and migrations effortless.
🧠 Local-first UX
TinyDebt doesn't rely on a server, so:
- actions apply instantly
- there's no loading or "syncing" states
- the app feels fast even on older phones
For a small personal utility, this fits perfectly.
🎨 UI philosophy
I wanted the app to feel "calm":
- simple neutral colors
- no charts or dashboards
- no clutter - one screen does 90% of the work
- accessible tap targets for quick entry
Small apps don't need complex visuals to be useful.
📦 Publishing
- Live on App Store
- Live on Google Play
But I want to keep the scope tiny - that's the whole point.
🙌 Feedback welcome
If you build mobile apps or have thoughts on local-first utilities, I'd love to hear feedback. Always improving.
