A modern, cross-platform expense tracking app built with React Native and Expo. Track your daily expenses, visualize spending patterns, and sync your data securely to GitHub.
- Quick Entry: Add expenses with amount, category, date, and notes
- Custom Categories: Create, edit, and reorder expense categories with custom colors and icons
- Payment Methods: Track how you pay (Cash, UPI, Credit Card, Debit Card, Net Banking, Amazon Pay, etc.)
- Saved Payment Instruments: Save your commonly used cards/UPI IDs with nicknames
- Cards store only last 4 digits, UPI stores only last 3 digits
- Expenses can reference a saved instrument by ID (CSV stays backward compatible)
- Default Payment Method: Set a preferred payment method for faster entry
- Full CRUD: Create, read, update, and delete expenses with ease
- History View: Browse expenses organized by date with comprehensive filters (time, amount, search, categories, methods, instruments) and cross-tab synchronization with Analytics
- Visual Charts: Bar charts showing daily spending patterns
- Category Breakdown: See spending distribution across categories
- Payment Method Analysis: Pie chart showing expense distribution by payment method
- Multi-Currency Support: Analytics automatically groups expenses by currency; filter chips appear when multiple currencies are present
- Advanced Filters: Filter by time period, categories, payment methods, saved instruments, amount range, and search text
- Cross-Tab Filter Sync: Filters applied in History automatically apply to Analytics and vice versa
- Instrument Breakdown: See spending per card/UPI nickname for selected payment methods
- Time-based Analysis: Track expenses over days/weeks/months plus 3m / 6m / 1y windows
- Amount Range Filtering: Filter expenses by minimum and maximum amounts
- Search: Search across expense notes, categories, payment methods, and instrument nicknames
- Secure Backup: Sync expenses to your private GitHub repository
- Optional Settings Sync: Also sync non-sensitive app settings (like categories and saved payment instruments) via
settings.json- Off by default; controlled by a toggle in Settings
- GitHub token/repo configuration is never synced (stays on-device)
- Daily File Organization: Expenses stored as
expenses-YYYY-MM-DD.csvfiles (one file per day) - Git-Style Sync: Fetch-merge-push workflow prevents accidental data loss
- Always fetches remote data before pushing
- Merges local and remote changes by expense ID
- Timestamp-based auto-resolution (newer version wins)
- True conflict detection when edits happen within the same time window
- Soft Delete: Expenses are marked with
deletedAttimestamp instead of being removed, ensuring deletions sync correctly across devices - Smart Sync:
- Auto-sync on app launch or after every change
- Manual sync with upload/download controls
- Incremental loading (last 7 days by default)
- Dirty-Day Sync: Tracks which days changed and only re-hashes/uploads those daily files
- Differential Sync: Only uploads changed files using content hashing for efficiency
- Batched Commits: All file changes (uploads and deletions) are combined into a single atomic commit
- Detailed Sync Feedback: Shows counts of expenses added, updated, and auto-resolved
- Load More: Download older expenses 7 days at a time
- Migration Support: Automatically migrates from old single-file format to daily files
- Multiple Languages: Full support for English (US, UK, IN), Hindi (ΰ€Ήΰ€Ώΰ€ΰ€¦ΰ₯), and Japanese (ζ₯ζ¬θͺ)
- Dynamic Locale Loading: Only the active locale is bundled at startup for faster app launch; other locales load on-demand when selected
- Locale Awareness:
- Currency symbols adapt to your choice ($, Β£, βΉ)
- Date formats match your region
- Per-Transaction Currency: Track expenses in any currency (useful for travel)
- Persistent Preferences: Remembers your language and default currency settings
- Cross-Platform: Works on iOS, Android, and Web
- Dark Mode: Automatic theme switching with proper token-based styling
- In-App Updates: Automatic update check on launch with non-intrusive banner notification
- Dismissible notifications that remember your choice per version
- Manual check available in Settings
- Opens Play Store or GitHub releases based on install source
- Shows a one-time βWhatβs Newβ changelog sheet on first launch after updating (when release notes exist)
- Reusable UI Components: Consistent styling with
ExpenseCard,AmountText,CategoryIcon,ScreenContainer,SectionHeader, andCategoryCard - Notifications: Toast messages for sync status and actions
- Offline First: Works without internet, syncs when connected
- First-Time Setup: Guided flow to download existing data
- Performance Optimized: Virtualized lists + memoized components/handlers for smooth scrolling with large datasets
- Node.js 24.x or higher
- Yarn 4.5.0 (included via packageManager)
- Expo CLI
- For iOS: Xcode and CocoaPods
- For Android: Android Studio and SDK
-
Clone the repository
git clone https://github.com/sudokoi/expense-buddy.git cd expense-buddy -
Install dependencies
yarn install
-
Start the development server
yarn start
-
Run on your platform
- iOS:
yarn ios - Android:
yarn android - Web:
yarn web
- iOS:
- Tap the + tab
- Enter the amount
- Select a category
- Add a note (optional)
- Choose your payment method
- If you selected Credit/Debit/UPI, optionally select a saved instrument (or choose Others and enter digits)
- Choose the date
- Tap Add Expense
- Go to the Settings tab
- Find Saved Instruments
- Tap Add to create a new card/UPI nickname
- Edit or remove instruments as needed (removals are soft-deletes so they sync correctly)
-
Sign in with GitHub (Android)
- Go to the Settings tab β GitHub Sync
- Tap Sign in with GitHub
- A browser will open and GitHub will show a short code
- Confirm the code and authorize access
- Back in the app, choose a personal repository you own
- Organization repositories are not supported
- Only repositories where you have write access are shown
- Enter/select a branch (usually
main) - Tap Save Config and then Test
-
Use a token instead (Web / fallback)
-
Create a GitHub Personal Access Token (PAT)
Option A: Fine-grained token (Recommended)
- GitHub Settings β Developer settings β Personal access tokens β Fine-grained tokens
- Generate new token, select the sync repository
- Permissions β Repository permissions β Contents: Read and write
Option B: Classic token
- GitHub Settings β Developer settings β Personal access tokens β Tokens (classic)
- Select the
reposcope (required for private repositories)
-
In the app, enter:
- Token
- Repository in
owner/repoformat - Branch (usually
main)
-
Tap Save Config and then Test
-
-
Enable Auto-Sync (Optional)
- Toggle Enable Auto-Sync
- Choose timing:
- On App Launch: Sync when app starts
- On Every Change: Sync after add/edit/delete
- Tap Save Auto-Sync Settings
Smart Sync:
- Tap Sync Now β uses git-style fetch-merge-push:
- Fetches all remote expenses first
- Merges with local data (newer timestamps win)
- Prompts only for true conflicts (same expense edited on both sides within seconds)
- Pushes merged result to remote
Auto-Sync:
- Happens automatically based on your settings
- Shows notifications when sync completes with detailed counts
- Handles conflicts using timestamps (latest wins)
- Scroll to bottom of History tab
- Tap Load More to download 7 more days
- Repeat to load older expenses
Expense Buddy follows a modular architecture with clear separation of concerns:
- Framework: React Native with Expo
- Routing: Expo Router (file-based routing)
- UI Library: Tamagui v1.144.0 (universal design system)
- State Management: XState Store v3 (reactive stores) + XState v5 (sync state machine)
- Storage: AsyncStorage + Expo SecureStore (with encryption utilities)
- Charts: react-native-gifted-charts
- Date Handling: date-fns
- CSV Parsing: PapaParse
- Testing: Jest + fast-check (property-based testing)
- Error Handling: Centralized error utilities with classification
- Type Safety: Comprehensive TypeScript with ServiceResult pattern
For detailed architecture documentation including:
- Store patterns and when to use each store type
- Hook decomposition strategy
- Performance optimization rationale
- Single-pass filtering algorithm
- Migration guides
See ARCHITECTURE.md
expense-buddy/
βββ app/ # Expo Router pages
β βββ (tabs)/ # Tab navigation screens
β βββ day/[date].tsx # Day detail view
β βββ _layout.tsx # Root layout
βββ components/ # Reusable components
β βββ analytics/ # Analytics chart components
β βββ ui/ # Styled UI components
β βββ history/ # History-specific components
βββ hooks/ # React hooks
βββ stores/ # XState Store state management
βββ services/ # Business logic
βββ utils/ # Utility functions
βββ constants/ # App constants
βββ types/ # TypeScript types
βββ locales/ # i18n translation files
For a complete component and service reference, see ARCHITECTURE.md. expense-buddy/ βββ app/ # Expo Router pages β βββ (tabs)/ # Tab navigation screens β β βββ index.tsx # Dashboard with charts β β βββ add.tsx # Add expense screen β β βββ history.tsx # Expense history with edit/delete β β βββ settings.tsx # Sync settings β β βββ _layout.tsx # Tab layout β βββ day/[date].tsx # Day detail view β βββ _layout.tsx # Root layout βββ components/ # Reusable components β βββ analytics/ # Analytics chart components β β βββ PaymentMethodPieChart.tsx # Payment method breakdown β β βββ CollapsibleSection.tsx # Collapsible chart wrapper β βββ ui/ # Styled UI components β β βββ AmountText.tsx # Styled amount display β β βββ CategoryCard.tsx # Category selection card β β βββ CategoryIcon.tsx # Category icon with background β β βββ ExpenseCard.tsx # Expense list item card β β βββ ScreenContainer.tsx # Screen wrapper with padding β β βββ SectionHeader.tsx # Section title component β β βββ DefaultPaymentMethodSelector.tsx # Payment method preference β β βββ PaymentMethodCard.tsx # Payment method display card β β βββ index.ts # Component exports β βββ Provider.tsx # App providers β βββ NotificationStack.tsx β βββ SyncIndicator.tsx βββ hooks/ # React hooks β βββ use-sync-machine.ts # XState sync machine React hook β βββ use-update-check.ts # In-app update check hook βββ stores/ # XState Store state management β βββ expense-store.ts # Expense data store β βββ settings-store.ts # App settings store β βββ notification-store.ts # Toast notifications store β βββ hooks.ts # Custom hooks (useExpenses, useSettings, etc.) β βββ store-provider.tsx # Store initialization provider β βββ index.ts # Store exports β βββ tests/ # Unit and property-based tests βββ services/ # Business logic β βββ sync-machine.ts # XState sync state machine (idle/fetching/merging/pushing/conflict/error) β βββ sync-manager.ts # Sync orchestration β βββ merge-engine.ts # Git-style merge logic (ID-based merge, timestamp resolution) β βββ github-sync.ts # GitHub API client (includes batch commit via Git Data API) β βββ csv-handler.ts # CSV import/export β βββ daily-file-manager.ts β βββ hash-storage.ts # Content hashing for differential sync β βββ change-tracker.ts # Record-level change tracking β βββ expense-storage.ts # Incremental local expense storage + migration β βββ payment-instruments.ts # Instrument utilities + validation β βββ payment-instruments-migration.ts # One-time linking migration for legacy expenses β βββ payment-instrument-merger.ts # Merge logic for syncing instruments β βββ auto-sync-service.ts βββ constants/ # App constants β βββ categories.ts β βββ payment-methods.ts # Payment method definitions β βββ payment-method-colors.ts # Chart colors for payment methods βββ tamagui.config.ts # Tamagui theme configuration with getColorValue helper βββ types/ # TypeScript types βββ expense.ts βββ payment-instrument.ts
## π§ͺ Testing
The app includes comprehensive unit tests and property-based tests:
```bash
# Run all tests
yarn test
# Run tests in watch mode
yarn test:watch
- Unit Tests: Coverage for services, stores, and critical utilities
- Property-Based Tests: fast-check properties validating merge/sync/store correctness
- Test Files: Located in
stores/__tests__/andservices/
The app does not require user-provided environment variables.
The GitHub OAuth Client ID is configured in app.config.js (not a secret). For Expo Go / local dev you can override it via EXPO_PUBLIC_GITHUB_OAUTH_CLIENT_ID.
Defined in eas.json:
- development: Development client with hot reload
- preview: Internal distribution for testing
- production: Production builds with auto-increment
- internal: APK builds for direct distribution
yarn start# iOS
eas build --platform ios --profile production
# Android
eas build --platform android --profile production
# APK for testing
eas build --platform android --profile internalSee .github/RELEASE.md for automated APK builds via GitHub Actions.
Found a bug or have a feature request? We'd love to hear from you!
In-App Reporting:
- Open the app and go to Settings
- Scroll to APP INFORMATION
- Tap Report an Issue
- Choose between Bug Report or Feature Request
GitHub Issues:
- Visit github.com/sudokoi/expense-buddy/issues
- Select the appropriate template
- Fill in the details
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Make your changes and create a changeset:
yarn changeset
- Commit your changes with the changeset:
git add . git commit -m 'feat: add some amazing feature'
- Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project uses Changesets for version management and automated changelog generation.
When contributing:
- Run
yarn changesetto document your changes - Select change type:
patch(bug fixes),minor(new features), ormajor(breaking changes) - Write a clear description of what changed
- Commit the generated changeset file with your PR
Automated releases:
- When PRs with changesets are merged, a "Version Packages" PR is automatically created
- Merging the Version PR triggers automatic tag creation
- Tag push triggers APK build and GitHub Release creation
- See .github/RELEASE.md for the full workflow
Expense Buddy does not collect any data. All your expense data is stored locally on your device. The optional GitHub sync feature uses your own credentials and repository. Read the full Privacy Policy.
This project is open source and available under the AGPL-3.0 License.
- Built with Expo
- UI powered by Tamagui
- Charts by react-native-gifted-charts
- Icons from Lucide
For questions or feedback, please open an issue on GitHub.
Made with β€οΈ using React Native and Expo

