https://github.com/davideagostini/dunio
Mobile-first Android app for shared household finance tracking with Firebase and Jetpack Compose.
https://github.com/davideagostini/dunio
android firebase firestore hilt household-finance jetpack-compose kotlin material3 mobile-app personal-finance
Last synced: 3 months ago
JSON representation
Mobile-first Android app for shared household finance tracking with Firebase and Jetpack Compose.
- Host: GitHub
- URL: https://github.com/davideagostini/dunio
- Owner: davideagostini
- License: mit
- Created: 2026-03-22T14:09:20.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-04-03T11:41:54.000Z (3 months ago)
- Last Synced: 2026-04-04T07:19:06.542Z (3 months ago)
- Topics: android, firebase, firestore, hilt, household-finance, jetpack-compose, kotlin, material3, mobile-app, personal-finance
- Language: Kotlin
- Homepage: https://dunio.app
- Size: 17.5 MB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
Dunio is a mobile-first Android app for shared household finance tracking.
It is designed for small shared workspaces such as couples or families who want a simple way to track:
- net worth
- assets and liabilities
- income and expenses
- recurring transactions
- monthly household progress
The app is intentionally not an accounting suite. The focus is fast daily use, clear numbers, and a simple shared-household model backed by Firebase.
## Screenshots







## What this repository contains
- Android app source code
- Gradle project files
- GitHub CI workflow
- contribution and release documentation
## Core product model
All financial data belongs to a `household`.
Supported roles:
- `owner`
- `member`
Both users share the same data inside a household:
- dashboard
- assets
- transactions
- categories
- recurring transactions
- month close state
Each household uses one shared currency configured from Settings. The app does not support per-asset currencies or mixed-currency totals.
## Current feature set
### Authentication and household
- Google sign-in with Firebase Authentication
- persistent session restore
- create household
- join household with invite + household ID
- owner/member household model
- household onboarding keeps the user behind a loading state until session access is fully resolved
### Dashboard
- net worth
- total assets
- total liabilities
- monthly cash flow
- savings rate
- financial runway
- 3 / 6 / 12 month net worth chart
- month selector
- full-screen get-started flow for households missing entries or assets
The dashboard now renders a lightweight skeleton state while its monthly summaries load, so the screen structure appears immediately instead of blocking behind a generic full-screen spinner.
### Entries
- monthly transaction list
- Firestore reads scoped to the selected month instead of the full household history
- grouped by day
- search
- entries / reports toggle in the toolbar
- `All / Expenses / Income` filter
- unusual spending insights
- category spending report with a horizontal bar chart plus totals, averages, percentages, and transaction counts
- entry edit and delete flow
- quick-entry flow
The entries screen now keeps the list and category reports month-scoped, while unusual-spending insights read only a small rolling window around the selected month instead of the full transaction archive.
It also renders a local shimmer skeleton during cold loads, so tab switches feel immediate even on slower devices.
### Assets
- monthly asset snapshots
- Firestore reads scoped to the selected month plus the previous month instead of the full asset history
- assets and liabilities in one feature
- search
- edit and delete flow
- copy previous month snapshot
- monthly net worth summary
- household currency applied automatically to new asset snapshots
The assets screen now reads only the selected month and previous month snapshots so list rendering, month-over-month change, and `Copy previous month` stay responsive without downloading the full asset archive.
Like Entries, it now uses a local shimmer skeleton during cold loads instead of blocking the whole app shell.
### Settings
- household currency
- app language selection
- app theme selection
- household data export to CSV or JSON
- category management
- recurring transactions
- month close
- household members
- invite management
- household details
The household currency is changed from a dedicated searchable settings screen, and the selected currency is surfaced at the top of the list.
The app also includes a dedicated language selection screen in Settings. It uses the same list style as the currency screen, keeps a stable alphabetical order, and highlights the currently selected language.
The app theme is also changed from a dedicated Settings screen using the same list treatment as language selection. Users can choose `Light`, `Dark`, or `System`, and the selected theme is persisted across launches.
The app also includes a dedicated export screen in Settings. It can export the current household as a full JSON backup, plus entries and assets as CSV files through the Android system document picker.
Recurring transactions can also be auto-applied on app startup. Once per day, after the session is ready, the app checks whether the current household has due recurring items for the current month and materializes them into the entries list without requiring a manual `Apply due` tap.
The month-close screen now reads only the selected month's entries and asset snapshots instead of loading the full transaction and asset history.
Bottom navigation now restores state across the primary tabs (`Dashboard`, `Entries`, `Assets`, `Settings`) so rapid tab switching reuses warm screens more reliably.
Current app-language support includes:
- English
- Italian
- French
- German
- Dutch
- Spanish
- Portuguese (Brazil)
- Russian
- Arabic
- Chinese (Simplified)
- Japanese
### Quick access
- Quick Settings tile
- home-screen quick-entry widget
- home-screen spending summary widget
## Tech stack
- Kotlin
- Jetpack Compose
- Material 3
- Hilt
- Coroutines + Flow
- Firebase Authentication
- Cloud Firestore
- Navigation Compose
- Glance widgets
## Project structure
Main source root:
```text
app/src/main/java/com/davideagostini/summ
```
Top-level packages:
```text
summ/
├── data/ # Firebase access, repositories, entities, session state, DI
├── domain/ # Shared models and lightweight use cases
├── tile/ # Quick Settings tile integration
├── ui/ # Compose screens, ViewModels, state, feature components
└── widget/ # Home-screen widgets and widget data sources
```
The current app pattern is:
```text
Screen composable
-> collects immutable state with collectAsStateWithLifecycle()
ViewModel
-> exposes uiState + renderState
Repository / Use Case
-> reads and writes Firebase-backed data
```
App text is resource-based and ready for Android per-app language switching through the system locale picker and the in-app language screen.
Composable screens should stay focused on rendering and screen orchestration. Derived business data such as totals, grouped lists, chart models, and filtered lists should be prepared in `ViewModel` or shared model/use-case code.
## Requirements
- Android Studio
- JDK 17
- Android SDK
- Firebase project
## Backend setup required
To actually run the app, you need your own Firebase project.
Minimum backend setup:
- Firebase Authentication with Google sign-in enabled
- Cloud Firestore created
- `app/google-services.json` added locally
- `firebase/firestore.rules` deployed
- `firebase/firestore.indexes.json` deployed
The provided Firestore rules support the initial household bootstrap flow used by the Android app:
- create household document
- create the owner membership
- seed default categories
This repository is app-first, but the Android client depends on that Firebase setup to work correctly.
## Local setup
### 1. Create a Firebase project
- Open [Firebase Console](https://console.firebase.google.com/)
- Create a new project
### 2. Register the Android app
Use this package name:
```text
com.davideagostini.summ
```
### 3. Enable Google sign-in
- Open `Authentication`
- Enable `Google`
- Set the support email if requested
### 4. Create Firestore
- Open `Firestore Database`
- Create a database
- Choose the mode you prefer for local development
### 5. Add Android SHA fingerprints
From the repository root:
```bash
cd mobile-app
./gradlew signingReport
```
Add the debug `SHA-1` and `SHA-256` fingerprints to the Android app in Firebase.
### 6. Add `google-services.json`
Download the file from Firebase and place it here:
```text
app/google-services.json
```
This file is intentionally ignored by Git.
### 7. Deploy Firestore rules and indexes
From the `mobile-app/firebase` folder:
```bash
cd mobile-app/firebase
firebase use --add
firebase deploy --only firestore:rules
firebase deploy --only firestore:indexes
```
If you prefer, you can deploy with `--project ` instead of setting an active project first.
### 8. Build and install
```bash
cd mobile-app
./gradlew assembleDebug
./gradlew installDebug
```
## Firestore data model
Expected structure:
```text
users/{uid}
households/{householdId}
households/{householdId}/members/{userId}
households/{householdId}/categories/{categoryId}
households/{householdId}/transactions/{transactionId}
households/{householdId}/assets/{assetId}
households/{householdId}/assets/{assetId}/history/{entryId}
households/{householdId}/recurringTransactions/{recurringTransactionId}
households/{householdId}/monthCloses/{period}
households/{householdId}/invites/{inviteId}
```
## Release signing
Create a local `keystore.properties` file by copying [`keystore.properties.example`](./keystore.properties.example) and filling in your local values.
Example:
```properties
storeFile=/absolute/path/to/your-upload-key.jks
storePassword=change-me
keyAlias=upload
keyPassword=change-me
```
Build a release bundle with:
```bash
cd mobile-app
./gradlew bundleRelease
```
The output bundle will be generated under:
```text
app/build/outputs/bundle/release/app-release.aab
```
## GitHub release automation
This repository is set up so that pushing a tag like `v0.0.5` can:
- build a signed release APK
- build a signed release AAB
- generate a release mapping file for deobfuscation
- keep optional native debug metadata and symbol tables as workflow artifacts when available
- publish both files to a GitHub Release
Required GitHub Actions secrets:
- `ANDROID_KEYSTORE_BASE64`
- `ANDROID_KEYSTORE_PASSWORD`
- `ANDROID_KEY_ALIAS`
- `ANDROID_KEY_PASSWORD`
- `GOOGLE_SERVICES_JSON_BASE64`
Release notes:
- CI validates that the decoded `google-services.json` matches `com.davideagostini.summ` and generates `default_web_client_id`
- release builds explicitly keep `@string/default_web_client_id` so `shrinkResources` does not remove Google Sign-In configuration
How it works:
1. Convert your keystore to base64 locally
2. Store the value in `ANDROID_KEYSTORE_BASE64`
3. Add the other signing values as repository secrets
4. Push a tag such as:
```bash
git tag v0.0.5
git push origin v0.0.5
```
The workflow will decode the keystore, sign the release build, generate both `APK` and `AAB`, and attach them to the Dunio GitHub Release.
Release builds use minification and resource shrinking. The generated `mapping.txt` is uploaded as a GitHub Actions artifact so you can keep the deobfuscation file for Play Console or post-release analysis without exposing it in the public GitHub Release. Native debug metadata and symbol tables are also uploaded as optional workflow artifacts when AGP produces them.
## Security and publishing notes
Do not commit:
- `app/google-services.json`
- `local.properties`
- `keystore.properties`
- `.jks` / `.keystore` files
- service account JSON files
If a local Firebase file was added to Git by mistake:
```bash
git rm --cached app/google-services.json
```
## Documentation
- [`CONTRIBUTING.md`](./CONTRIBUTING.md)
- [`project_overview.md`](./project_overview.md)
- [`FIRST_RELEASE_CHECKLIST.md`](./FIRST_RELEASE_CHECKLIST.md)
- [Privacy Policy](https://dunio.app/privacy-policy)
- [Terms of Service](https://dunio.app/terms-of-service)
## Roadmap ideas
### High Priority · Lower Effort
- income vs expense analysis with category breakdown
- improved home-screen widgets
- user feedback mechanism
### High Priority · Medium Effort
- budgets with weekly, monthly, and yearly spending limits by category
- reports and summaries for monthly review
- notifications and reminders
### Future Additions · Higher Effort
- import transactions from CSV with validation
- bank CSV import support
- better backup and migration flows
- Wear OS support
- AI-powered finance features
## Support the project
Dunio is free to use and open source. If you find it useful and want to support ongoing development, you can do it here:
- [Buy Me a Coffee](https://buymeacoffee.com/davideagostini)
- [GitHub Sponsors](https://github.com/sponsors/davideagostini)
## Star History
If you find Dunio useful, consider giving the repository a star.
[](https://app.repohistory.com/star-history)
## License
This repository uses the MIT license. See [`LICENSE`](./LICENSE).
