Personal & Family Finance Management β Built with React + Firebase
Dompet Keluarga ("Family Wallet") is a full-featured, cloud-synced personal finance web app for Indonesian families. Track transactions, investments, savings goals, budgets, and subscriptions β all from one place.
| Feature | Description |
|---|---|
| Financial Health Score | 0β100 score based on savings rate, budget adherence, debt ratio, and investment coverage |
| Cash Flow Trend | 6-month income vs. expense line chart |
| Asset Growth | Area chart tracking investment portfolio growth |
| Month-over-Month | Grouped bar chart comparing top spending categories vs. prior month |
| Budget Monitoring | Real-time progress bars with alerts at 90% threshold |
| Per-Account Balances | Scrollable snapshot of all wallets with credit-limit indicators |
- Income, Expense, and Transfer between accounts
- Filter by date range and wallet
- Export to CSV (UTF-8 BOM for Excel compatibility)
- Automatic categorisation with full edit history
- Bank, Cash, Credit Card (with limit tracking), E-Wallet, PayLater (GoPay Later, Kredivo, etc.), RDN (Rekening Dana Nasabah for stock accounts)
- Custom name, icon, and emoji support
- Running balance computed from transaction history
- Set a name, target amount, target date, and linked wallet
- Progress bar with months remaining and required monthly contribution
- Status badges: On Track / Needs Attention / Overdue / Achieved
- 5-step Budget Wizard: choose 50/30/20, 70/20/10, or fully custom % splits
- Per-category monthly allocation with auto-save to Firestore
- Salary Allocator: multi-source income, carry-over from previous month, pie-chart visualisation
- Monthly transaction history table with totals
- Gold, stocks, mutual funds, and custom asset types
- Market value tracking with unrealised P&L per asset
- Zakat calculator with real-time gold-price integration
- Auto-icon mapping for 50+ popular services (Netflix, Spotify, Adobe, GitHubβ¦)
- Renewal date tracking and monthly cost summary
- Chat interface powered by Google Gemini or any OpenRouter model (incl. free Llama 3.3, Qwen3)
- Contextual prompts auto-populated with your current financial snapshot
- API keys stored only in
localStorageβ never sent to the app server
- Upload a receipt screenshot β Google Cloud Vision OCR extracts line items automatically
- Multi-transaction preview table: edit amount, category, account, date
- Privacy-first: the image is deleted from memory immediately after saving; it is never stored in Firebase
| Multi-currency | IDR, USD, SGD, EUR, MYR, JPY, AUD with live exchange rates |
| Bahasa / English | Full i18n toggle |
| Dark mode | Full dark theme across all views |
| Privacy mode | Replace all numbers with bullets ( β’ ) |
| Material Design 3 | Full MD3 color token system β surface containers, roles, dynamic color |
| Education Fund | Dedicated savings planner for education costs |
| Income Diversification | Track multiple income streams |
| Salary Slip Archive | Store and parse payslip PDFs |
| Google Sign-In | Firebase Auth β one-click, no passwords |
| Real-time sync | onSnapshot Firestore listeners |
| Mobile-first | Responsive layout with pull-to-refresh |
v2.1 Design System β Every view is built on a Material Design 3 token foundation. Colors reference semantic roles (
primary,on-surface,surface-container-*,secondary-container,error-container,tertiary-fixed, etc.) defined once intailwind.config.js, illustrated by the Manrope typeface and Material Symbols Outlined icon set.
| Layer | Technology |
|---|---|
| Framework | React 19 + Vite 7 |
| Styling | Tailwind CSS v3 |
| Database | Firebase Firestore (real-time) |
| Auth | Firebase Authentication (Google OAuth 2.0) |
| Charts | Recharts |
| Icons | Material Symbols Outlined (variable font) |
| Design System | Material Design 3 color tokens via Tailwind CSS |
| Typography | Manrope (Google Fonts) |
| AI | Google Gemini API, OpenRouter API |
| OCR | Google Cloud Vision API |
| i18n | Custom useI18n hook + translations.js |
- Node.js β₯ 18
- A Firebase project (free Spark plan is sufficient)
git clone https://github.com/YOUR_USERNAME/dompet-keluarga.git
cd dompet-keluarga
npm installcp .env.example .env.localOpen .env.local and paste your Firebase project values (found in Project Settings β General β Your apps β SDK setup):
VITE_FIREBASE_API_KEY=AIzaSy...
VITE_FIREBASE_AUTH_DOMAIN=my-project.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=my-project
VITE_FIREBASE_STORAGE_BUCKET=my-project.firebasestorage.app
VITE_FIREBASE_MESSAGING_SENDER_ID=123456789
VITE_FIREBASE_APP_ID=1:123456789:web:abc123
VITE_FIREBASE_MEASUREMENT_ID=G-XXXXXXXXXX
VITE_APP_ID=dompet-keluarga # Firestore root namespace β change freely- Firebase Console β Authentication β Sign-in method
- Enable Google
- Add
http://localhost:5173to Authorized domains
# Install Firebase CLI if needed
npm install -g firebase-tools
firebase login
# Copy .env.example to .firebaserc (fill in your project ID), then:
firebase deploy --only firestore:rulesOr paste the contents of firestore.rules manually in the Firebase Console.
npm run dev
# β http://localhost:5173The app has a built-in Demo Mode that activates automatically when VITE_FIREBASE_API_KEY is not set.
In Demo Mode:
- No Firebase account or project required β works fully offline
- All data is stored in
localStorageon the visitor's browser - A banner is shown at the top of the app making it clear it is a demo
- The Firebase SDK is completely excluded from the bundle (saves ~340 KB)
- Sign-in is instant with a pre-populated "Demo User"
vite.config.jsaliasesfirebase/app,firebase/auth, andfirebase/firestoreto stubs insrc/lib/β no view or hook files need any demo-specific branching- The Firestore mock supports:
collection,doc,addDoc,setDoc,updateDoc,deleteDoc,getDoc,getDocs,writeBatch,onSnapshot,serverTimestamp,increment,arrayUnion,arrayRemove,where,orderBy,query
To deploy the live demo on GitHub Pages:
- Push the repo to GitHub.
- Enable Pages: Settings β Pages β Source β GitHub Actions
- Do NOT add any Firebase secrets β leave them all blank (or simply skip step 3 of Option A)
- Push to
mainβ the workflow builds and deploys automatically in Demo Mode
For a fully functional deployment where each user has their own cloud-synced data:
-
Push the repo to GitHub.
-
Enable Pages: Settings β Pages β Source β GitHub Actions
-
Add your Firebase credentials as repository secrets: Settings β Secrets and variables β Actions β New repository secret
Secret name Value VITE_FIREBASE_API_KEYYour API key VITE_FIREBASE_AUTH_DOMAINyour-project.firebaseapp.comVITE_FIREBASE_PROJECT_IDyour-projectVITE_FIREBASE_STORAGE_BUCKETyour-project.firebasestorage.appVITE_FIREBASE_MESSAGING_SENDER_IDSender ID VITE_FIREBASE_APP_IDApp ID VITE_FIREBASE_MEASUREMENT_IDG-XXXXXXXXXXVITE_APP_IDdompet-keluarga -
Push to
mainβ the deploy workflow builds and publishes automatically. -
Add the Pages URL to Firebase Auth Authorized domains (e.g.
YOUR_USERNAME.github.io).
The workflow automatically sets
VITE_BASE_URL=/dompet-keluarga/so all asset paths resolve correctly under the sub-path.
npm run build
firebase deploy --only hostingnpm run build # output: dist/Upload the dist/ folder. For Netlify/Vercel, set the build command to npm run build and publish directory to dist. Remember to add the hosting domain to Firebase Auth Authorized domains.
dompet-keluarga/
βββ .env.example # Environment variable template
βββ .github/
β βββ workflows/
β βββ deploy.yml # GitHub Actions β build & deploy to Pages
βββ firestore.rules # Firestore security rules
βββ firestore.indexes.json # Firestore composite indexes
βββ public/
β βββ manifest.json # PWA manifest
βββ src/
βββ App.jsx # Root: auth, routing, global state
βββ config/
β βββ firebase.js # Firebase initialisation (env-var driven)
βββ lib/
β βββ demoApp.js # firebase/app stub (demo mode)
β βββ demoAuth.js # firebase/auth stub β auto-logs in "Demo User"
β βββ demoDb.js # localStorage-backed Firestore mock (collection, doc,
β # addDoc, setDoc, updateDoc, deleteDoc, getDoc, getDocs,
β # writeBatch, onSnapshot, serverTimestamp, increment,
β # arrayUnion, arrayRemove, where, orderBy, queryβ¦)
βββ components/
β βββ layout/
β β βββ Sidebar.jsx # Navigation sidebar + MobileMenu + AppFooter
β β βββ AIAdvisorPanel.jsx # Slide-in AI chat panel
β βββ modals/
β β βββ BudgetWizard.jsx # 5-step budget setup wizard
β β βββ TransactionModal.jsx # Add/edit transaction
β β βββ QuickAddModal.jsx # Receipt scanner (Vision API)
β βββ ui/
β β βββ index.jsx # Shared UI primitives (Card, NavBtnβ¦)
β β βββ LoginPage.jsx
β βββ views/ # Full-page view components (lazy-loaded)
β βββ DashboardView.jsx
β βββ TransactionView.jsx
β βββ WalletView.jsx
β βββ SavingsGoalView.jsx
β βββ AIAdvisorView.jsx
β βββ InvestmentView.jsx
β βββ SalaryAllocatorView.jsx
β βββ SubscriptionView.jsx
β βββ CategoryView.jsx
β βββ ZakatView.jsx
β βββ ...
βββ constants/ # Category lists, currency config, service icons
βββ hooks/
β βββ useAppData.js # Firestore onSnapshot listeners for all collections
βββ i18n/
β βββ I18nContext.jsx
β βββ translations.js # Indonesian + English strings
βββ utils/
βββ api.js # External API helpers (exchange rate, gold price)
βββ formatters.js # Currency & date formatting (Intl API)
βββ healthScore.js # Financial Health Score calculator
βββ parsers/ # Receipt / Vision API parsing utilities
All data lives under /artifacts/{VITE_APP_ID}/users/{uid}/:
| Collection | Description |
|---|---|
transactions |
Income, expense, transfer records |
wallets |
Account definitions (bank, CC, e-walletβ¦) |
categories |
Custom categories with monthly budget |
subscriptions |
Recurring service subscriptions |
investments |
Individual investment positions |
investmentTypes |
Custom asset types (gold, stocksβ¦) |
savings_goals |
Savings targets with progress tracking |
monthly_controls/{month} |
Salary allocation snapshots per month |
settings/visionApi |
Vision API key (user-scoped, encrypted by Firestore rules) |
- No secrets in source code β all credentials loaded via
import.meta.envfrom.env.local(git-ignored). - Firestore rules enforce per-user isolation β users can only read/write their own documents (
request.auth.uid == userId). - AI API keys are localStorage-only β never persisted to Firestore or transmitted to any first-party server.
- Vision API images are ephemeral β deleted from memory immediately after transaction extraction; never written to Firebase Storage.
.firebasercis git-ignored β your Firebase project alias stays local.
See PRIVACY_SECURITY.md for a full security audit.
Contributions are welcome! Here's how:
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Commit with a clear message:
git commit -m 'feat: add your feature' - Push and open a Pull Request against
main
Please follow these guidelines:
- Keep PRs focused β one feature or fix per PR
- Run
npm run lintbefore pushing - Don't commit
.env.localordist/
This project is licensed under the MIT License β see the LICENSE file for details.
- React β UI library
- Vite β Build tool
- Firebase β Auth & database
- Tailwind CSS β Styling
- Recharts β Chart library
- Lucide Icons β Icon set
- Budggt β Feature inspiration
Dompet Keluarga β Kelola Keuangan Keluarga dengan Bijak π
Made with β€οΈ for Indonesian families