A simple personal finance app built with Flutter to track monthly incomes and expenses and quickly see your balance.
- Add monthly expenses and incomes
- Mark items as recurring (monthly) or one-time
- Tag items for categorization (e.g. "Home", "Work", "Subscriptions")
- Month selection with automatic filtering
- Automatic calculation of totals and balance per month
- Swipe to delete items
- Edit existing items
- Local persistence (data survives app restarts)
- Currency selection (EUR, USD, GBP, CHF)
- Toggle to show/hide tags on item cards
- Settings with tag management (rename/delete tags)
- Filter items by tags or recurring status
- Statistics with monthly breakdown by tag and recurring vs one-time charts
-
Global App State
- Stored in a singleton
AppState - Implemented using
ChangeNotifier - Exposed via
provider
- Stored in a singleton
-
Business Logic
- Lives inside
AppState - UI never calculates totals directly
- Lives inside
-
UI
- Pages are responsible for UI structure only
- Reusable components live in
widgets/ - State is read using
context.watch<AppState>()
AppStateis the single source of truth- All mutations call
notifyListeners() - Widgets read state and trigger actions, but never contain business rules
Example:
context.read<AppState>().addExpense(item);- Files:
snake_case.dart - Classes:
PascalCase - Variables & methods:
camelCase - Widgets:
- Pages →
SomethingPage - Reusable widgets → descriptive nouns (
BalanceCard,ItemList)
- Pages →
- Global state →
AppState - UI-only state →
StatefulWidget - No logic inside
build()other than layout decisions
- Immutable data classes
- No logic inside models
- Pure data containers