Building a Personal Finance App with Flutter from Scratch
Personal finance apps are a great learning ground for Flutter — they touch everything: local data persistence, state management, complex UI, charts, and notifications.
Why Flutter?
Flutter gives you a single codebase that compiles to native iOS, Android, macOS, and Web. For a finance app that users want on every device, this is a massive advantage.
Architecture: Clean + Riverpod
We chose Clean Architecture with Riverpod for state management. The three layers are:
- Data Layer: SQLite via
driftfor local persistence - Domain Layer: Use cases and repositories
- Presentation Layer: Riverpod providers + Flutter widgets
// A simple transaction notifier
@riverpod
class TransactionsNotifier extends _$TransactionsNotifier {
@override
Future<List<Transaction>> build() async {
return ref.read(transactionRepositoryProvider).getAll();
}
Future<void> add(Transaction tx) async {
await ref.read(transactionRepositoryProvider).insert(tx);
ref.invalidateSelf();
}
}
Local Database with Drift
Drift (formerly Moor) gives you type-safe SQLite access with a great reactive API:
@DriftDatabase(tables: [Transactions, Categories])
class AppDatabase extends _$AppDatabase {
AppDatabase() : super(NativeDatabase.createInBackground(dbFile));
@override
int get schemaVersion => 1;
}
Charts with fl_chart
The fl_chart package handles all our data visualisation. Pie charts for category breakdown, line charts for net worth over time, and bar charts for monthly spending.
Key Lessons
- Design your DB schema first — changing it later with migrations is painful
- Riverpod over BLoC for smaller teams — less boilerplate, easier to test
- Avoid over-engineering — start with a flat list, add categories only when users ask
What's Next
In the next post we'll cover adding sync to the cloud using Supabase, so users can access their data across devices without sacrificing offline-first behaviour.