Kahavanu
An offline-first Android personal finance application built with Kotlin, Jetpack Compose, and Room.
The origin
Named after the historic gold coinage of ancient Sri Lanka, Kahavanu was built to solve a persistent frustration with modern expense trackers: reliance on constant internet connectivity.
Most contemporary finance applications behave like web wrappers. They require server handshakes for every transaction log, spin endlessly when mobile reception drops in a store, and lock your personal financial records behind third-party cloud availability.
I wanted a personal finance tool that felt instant, reliable, and completely functional offline, whether you are recording a small transit fare on spotty mobile data or reviewing monthly savings goals in airplane mode.
Local-first architecture
Kahavanu is engineered around a local-first philosophy, treating the device's local storage as the primary source of truth:
- Room local database: Every transaction, income stream, and savings goal is committed immediately to an encrypted local Room SQLite database on the device, eliminating input latency.
- WorkManager background synchronization: Changes made while offline are tracked in a mutation queue and synchronized seamlessly to Firebase Firestore whenever an active network connection is detected.
- Recurring cash flow management: Automatically forecasts upcoming recurring subscriptions, scheduled bills, and expected income cycles to display true net balance.
- Goal tracking: Allows users to establish dedicated savings targets with real-time progress calculations as surplus funds are allocated.
Modern Android engineering
The codebase follows Google's recommended Android architecture practices for long-term maintainability:
- Jetpack Compose UI: Declarative UI built entirely with Jetpack Compose and Material 3 design tokens, providing dynamic dark mode support and fluid animations.
- Unidirectional data flow: Built on the MVVM pattern where Compose screens observe immutable UI state exposed via Kotlin
StateFlowfrom ViewModels. - Dependency injection: Dependency inversion managed via Dagger Hilt, keeping UI screens strictly decoupled from repository interfaces and database implementations.
Tech stack
- Language: Kotlin 2.2
- UI Framework: Jetpack Compose with Material 3
- Local Storage: Android Room
- Cloud Sync: Firebase Firestore and Firebase Authentication
- Background Processing: Android WorkManager
- Dependency Injection: Hilt