2.3 KiB
Architecture — Decisions & Rationale
ADR-001: Flutter as framework
Decision: Flutter (not React Native or native). Reason: Single codebase for Android + iOS + Web; Dart type safety; strong Material 3 support; flet-managed Flutter SDK already present.
ADR-002: Riverpod for state management
Decision: Riverpod with code generation (riverpod_annotation).
Reason: Compile-time safety; no BuildContext required for providers;
excellent async support (AsyncNotifier); easy testing via ProviderContainer overrides.
Rejected: Bloc (too verbose), Provider (deprecated patterns), GetX (opinionated anti-patterns).
ADR-003: Drift (formerly Moor) for local database
Decision: Drift + sqlite3_flutter_libs. Reason: Type-safe SQL in Dart; reactive streams out of the box; strong migration support; works on all Flutter platforms incl. Web (via WASM). Rejected: Hive (no relations), Isar (less mature migration story).
ADR-004: Offline-first, no backend
Decision: All data stored locally on device.
Reason: Privacy, no auth complexity, works without internet.
Future: optional cloud sync (Supabase/Firebase) can be added as a separate
sync feature without touching existing data layer.
ADR-005: go_router for navigation
Decision: go_router with StatefulShellRoute. Reason: Official Flutter navigation package; deep link support; URL-based routing works for Web target; StatefulShellRoute preserves bottom-nav state.
ADR-006: Feature-first directory structure
Decision: lib/features/<name>/{data,domain,presentation}/
Reason: Features can be developed and reviewed in isolation; clear
ownership; easier to add/remove features without touching unrelated code.
Each feature's data/ holds repositories and DAOs, domain/ holds models
and providers, presentation/ holds screens and widgets.
ADR-007: freezed for domain models
Decision: All domain models use freezed.
Reason: Immutability enforced at compile time; copyWith generated;
== and hashCode correct; union types for state (e.g. TimerState).
ADR-008: Multilingual from day one
Decision: flutter_localizations + ARB files, no hardcoded strings.
Reason: Avoids costly retro-fitting; supports en + de initially;
easily extensible by adding new ARB files.