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 StateFlow from 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