← Back to projects

Numo

📱 Android App Kotlin · SQLite · MVVM 2025 ✓ Actually used
Numo home screen Numo charts Numo expenses

An offline-first Android expense tracker. No account required. No cloud. No privacy policy to scroll through. Everything lives in SQLite on your phone. My sister and I use it daily.

"Most finance apps require an account, sync to the cloud, and have someone else's server holding your data. Numo doesn't do any of that."

— The reason I built it

Features

🏠

Home dashboard

Monthly spending vs budget at a glance. Remaining budget, recent transactions, one tap to add a new expense.

🔍

Search & filter

Full transaction history grouped by date. Search by name, filter by category (Alimentación, Hogar, Ocio, Salud...).

🔁

Recurring expenses

Set up subscriptions once. Configure periodicity (monthly/quarterly/yearly), billing day, and advance notification (1 day, 3 days, same day).

🎯

Budget limits

Set spending caps per category with a visual progress bar. Edit or remove limits at any time.

📊

Charts & stats

Pie chart by category, 6-month evolution bar chart, month-over-month comparison with % change.

📤

Export

Export all expenses to CSV or generate a monthly PDF report. Your data, your format, your device.

Screenshots

Home screen Expenses list Charts Budget limits Recurring payments Settings

Tech stack

Kotlin SQLite MVVM Android SDK Material Design WorkManager Room Database PDF generation CSV export Gradle (Kotlin DSL)

What I learned

Designing a local-first app means thinking differently about data. There's no API to fall back on — if the SQLite schema is wrong, everything breaks. I spent more time on the database design than I expected, especially around the recurring expenses logic.

The recurring expenses feature was the trickiest part: figuring out when to trigger notifications, how to handle missed payments, and how to make the periodicity logic work cleanly without overcomplicating the data model.

Also: export to PDF from an Android app is way more annoying than it sounds. But it works, and that's the point.