16 KiB
16 KiB
Stack Research
Domain: Local-first Flutter household chore management app (Android-first) Researched: 2026-03-15 Confidence: HIGH (versions verified directly from pub.dev; compatibility notes cross-checked against GitHub issues and official docs)
Recommended Stack
Core Technologies
| Technology | Version | Purpose | Why Recommended |
|---|---|---|---|
| Flutter SDK | ^3.41.x (stable) | UI framework and build toolchain | Current stable. Riverpod 3.3.x requires Dart 3.7+; Flutter 3.41 ships Dart 3.7. Earlier stable releases (pre-3.41) had a transitive analyzer conflict with Riverpod 3.2+ that was fixed in 3.41.1. |
| Dart SDK | ^3.7.0 | Language runtime | Minimum required by flutter_riverpod ^3.3.0. Set as lower bound in pubspec.yaml. |
| flutter_riverpod | ^3.3.1 | State management and dependency injection | The project already decided on Riverpod. v3.x is current stable (released Sep 2025); it unifies AutoDispose/Family variants, simplifies Ref (no more subclasses), and adds built-in offline persistence (opt-in). Start on v3 — migrating from v2 later is painful. |
| riverpod_annotation | ^4.0.2 | Annotations for code-generation-based providers | Enables @riverpod annotation. Required companion to riverpod_generator. Code-gen is the recommended path in Riverpod 3 — less boilerplate, compile-safe, autoDispose by default. |
| drift | ^2.32.0 | Type-safe reactive SQLite ORM | The project already decided on Drift. Reactive streams (.watch()) integrate naturally with StreamProvider in Riverpod. Type-safe query generation catches errors at compile time. Built-in migration support is essential for a long-lived local-first app. |
| drift_flutter | ^0.3.0 | Flutter-specific Drift setup helper | Bundles sqlite3_flutter_libs, handles getApplicationDocumentsDirectory() automatically. Eliminates manual SQLite platform setup on Android. Use driftDatabase(name: 'household_keeper') to open the DB. |
Supporting Libraries
| Library | Version | Purpose | When to Use |
|---|---|---|---|
| freezed | ^3.2.5 | Immutable value objects with copyWith, equality, pattern matching | Use for all domain entities (Room, Task, TaskCompletion) and Riverpod state classes. @freezed + code-gen eliminates hand-written == / copyWith. |
| freezed_annotation | ^3.1.0 | Annotations for freezed code generation | Required companion to freezed. Always add to dependencies (not dev_dependencies). |
| go_router | ^17.1.0 | Declarative URL-based navigation | Official Flutter team package. The app has shallow navigation (RoomList → TaskList → DailyPlan), but GoRouter's ShellRoute cleanly handles a bottom nav bar with persistent state per tab. Simple enough for this app's needs; widely supported. |
| flutter_local_notifications | ^21.0.0 | Scheduled local notifications | For the daily summary notification (required by PROJECT.md). No Firebase needed — purely on-device scheduling via Android's AlarmManager. Requires Android 7.0+ (API 24). |
| timezone | ^0.11.0 | Timezone-aware scheduled notifications | Required by flutter_local_notifications for reliable scheduled notification timing across daylight-saving boundaries. |
| flex_color_scheme | ^8.4.0 | Material 3 theme generation | Generates a fully consistent M3 ThemeData — including legacy color properties that ColorScheme.fromSeed() misses — from a single seed color. The calm muted-green palette specified in PROJECT.md is straightforward to express as a seed color. Reduces ~300 lines of manual theme code to ~20. |
| intl | ^0.19.0 | Date and number formatting; localization infrastructure | Format due dates (German locale: dd.MM.yyyy), relative strings ("übermorgen", "heute"). Also the underlying engine for flutter_localizations. Even for a German-only MVP, you still need date formatting. |
Development Tools and Code-Generation Packages
| Tool / Package | Version | Purpose | Notes |
|---|---|---|---|
| riverpod_generator | ^4.0.3 (dev) | Generates provider boilerplate from @riverpod annotations |
Run dart run build_runner watch -d during development. The -d flag deletes conflicting outputs before building. |
| drift_dev | ^2.32.0 (dev) | Generates type-safe Drift query code from table definitions | Same build_runner run handles both Drift and Riverpod generation. |
| build_runner | ^2.12.2 (dev) | Orchestrates all code generation | One build_runner watch invocation covers all generators in the project. |
| freezed (dev) | ^3.2.5 (dev) | Generates immutable class implementations | Note: freezed appears in both dependencies (as annotation) and dev_dependencies (as generator). freezed_annotation goes in dependencies, freezed itself in dev_dependencies. |
| flutter_lints | ^6.0.0 (dev) | Official Flutter lint ruleset | Default in new Flutter projects. Catches common errors and style issues. Extend with stricter rules in analysis_options.yaml as the codebase grows. |
| riverpod_lint | ^4.0.x (dev) | Riverpod-specific lint rules | Catches incorrect provider usage: unused providers, missing ref.watch inside builds, incorrect async patterns. Add alongside flutter_lints. Check exact version on pub.dev at setup time — tracks riverpod_generator versions. |
pubspec.yaml
name: household_keeper
description: Local-first chore management app for Android.
version: 1.0.0+1
environment:
sdk: ^3.7.0
flutter: ">=3.41.0"
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
# State management
flutter_riverpod: ^3.3.1
riverpod_annotation: ^4.0.2
# Database
drift: ^2.32.0
drift_flutter: ^0.3.0
# Immutable models
freezed_annotation: ^3.1.0
# Navigation
go_router: ^17.1.0
# Notifications
flutter_local_notifications: ^21.0.0
timezone: ^0.11.0
# Theming
flex_color_scheme: ^8.4.0
# Localization / date formatting
intl: ^0.19.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^6.0.0
# Code generation
riverpod_generator: ^4.0.3
riverpod_lint: ^4.0.0 # verify exact version on pub.dev at setup time
build_runner: ^2.12.2
drift_dev: ^2.32.0
freezed: ^3.2.5
flutter:
generate: true # required for flutter_localizations ARB code gen
Alternatives Considered
| Category | Recommended | Alternative | Why Not Alternative |
|---|---|---|---|
| State management | Riverpod 3.x | flutter_bloc | Project already decided Riverpod. Bloc requires more boilerplate (events, states, blocs) for what this app needs. Riverpod integrates more naturally with Drift's reactive streams. |
| State management | Riverpod 3.x | Riverpod 2.x | v2 is no longer maintained upstream. v3 was released Sep 2025; migrating later is a breaking-change effort. Start on v3 now. |
| Database | Drift | Isar | Isar is a NoSQL document store — less natural for the relational structure (rooms → tasks → completions). Drift's reactive streams fit Riverpod's StreamProvider perfectly. Isar's future is uncertain after its maintainer handed it off. |
| Database | Drift | ObjectBox | ObjectBox is a NoSQL object store. Same relational argument applies. Drift's SQL gives more flexibility for complex queries (e.g., "overdue tasks per room" with joins). ObjectBox has a commercial tier for some features. |
| Database | Drift | sqflite + raw SQL | Raw sqflite requires manual query strings, manual mapping, no reactive streams, no compile-time safety. The project explicitly chose Drift over raw sqflite for type safety and migration support. |
| Navigation | go_router | auto_route | auto_route has slightly better type safety but requires more setup. go_router is an official Flutter package — simpler, well-documented, maintained by the Flutter team. Good enough for this app's flat navigation graph. |
| Navigation | go_router | Navigator 2.0 (raw) | Excessive boilerplate for a 4-screen app. go_router wraps Navigator 2.0 cleanly. |
| Theming | flex_color_scheme | Manual ThemeData | Manual M3 theming misses legacy color sync (e.g., ThemeData.cardColor, dialogBackgroundColor still default to wrong values without explicit override). flex_color_scheme fills all gaps. For a calm, consistent design, the investment of one dependency is worth it. |
| Theming | flex_color_scheme | dynamic_color (Material You) | Dynamic color adapts to wallpaper — inappropriate for a fixed calm-palette design. The app defines its own identity; it should not shift colors based on user wallpaper. |
| Notifications | flutter_local_notifications | awesome_notifications | awesome_notifications is more powerful but significantly heavier. flutter_local_notifications is sufficient for a single daily scheduled notification. |
| Localization | flutter_localizations + intl | easy_localization | For German-only MVP, flutter_localizations with ARB files is the official path. easy_localization adds another dependency with no benefit until multi-language is needed. When English is added in v1.1, the ARB infrastructure is already in place. |
What NOT to Use
| Avoid | Why | Use Instead |
|---|---|---|
| Provider (package) | Predecessor to Riverpod, now in maintenance mode. Much weaker compile-time safety. Migration from Provider to Riverpod later is non-trivial. | flutter_riverpod ^3.3.1 |
| StateNotifierProvider / StateProvider (Riverpod legacy) | Moved to package:flutter_riverpod/legacy.dart in Riverpod 3.0. The official docs now use @riverpod + AsyncNotifier / Notifier. Using legacy providers means you will need to migrate soon after starting. |
@riverpod annotated AsyncNotifier / Notifier classes |
| Hive | No first-class SQLite support. Key-value store with no query language — cannot express "tasks due today across all rooms" without loading the entire dataset. Hive v2 has had stale maintenance; Isar (its successor) is now also uncertain. | Drift |
| Firebase (any service) | PROJECT.md is explicit: zero backend, zero network dependencies, no analytics, no tracking. Firebase Firestore, Firebase Analytics, Firebase Crashlytics, Firebase Auth — all out of scope. | Nothing; handle everything locally. |
| GetIt (service locator) | Riverpod already handles DI through providers. Using GetIt alongside Riverpod creates two competing DI systems and makes provider scoping/testing harder. | Riverpod providers as the single DI mechanism |
| MobX | Not compatible with Riverpod. Requires its own code generation and observable pattern. Complexity without benefit when Riverpod 3.x already handles reactive state. | flutter_riverpod + riverpod_generator |
| flutter_bloc alongside Riverpod | Two competing state systems in one codebase creates cognitive overhead and testing complexity. | Pick one: Riverpod for this project. |
StateNotifier (standalone package) |
Deprecated upstream. Riverpod 3.x Notifier replaces it. |
Notifier<T> with @riverpod |
Stack Patterns by Variant
For reactive Drift queries (read-only list screens):
- Use
@riverpod Stream<List<T>>backed by a DAO.watch()method - The screen consumes via
ref.watch(roomsProvider)returningAsyncValue<List<Room>> - Drift emits a new list automatically when the database changes — no manual invalidation
For mutations (completing a task, adding a room):
- Use
@riverpod class TaskNotifier extends AsyncNotifier<void>with explicit methods - Call
ref.invalidate(tasksProvider)after mutation to trigger rebuild on affected watchers - In Riverpod 3.x, the new experimental
MutationAPI is available but still experimental — use manual invalidation for stability
For the daily plan (complex cross-room query):
- Implement a Drift query that joins tasks + rooms filtered by due date
- Expose via
@riverpod Stream<DailyPlanSummary>so the plan view auto-updates as tasks are completed - Do NOT compute the daily plan in the UI layer — push join logic into a DAO method
For notification scheduling:
- Schedule the daily notification at app startup (in a
ProviderScopeoverride orapp.dartinitState) - Re-schedule when the user completes all tasks for the day or explicitly changes notification time
- Notification scheduling is one-time daily, not per-task — keeps it simple for MVP
For German-only MVP localization:
- Use hardcoded German strings in widgets for MVP rather than ARB files
- Set up the ARB infrastructure skeleton (
l10n.yaml,lib/l10n/app_de.arb) before v1.1 so adding English is a string extraction exercise, not an architectural change - Do NOT use
String.fromCharCodesor runtime locale detection — always targetde
Version Compatibility Notes
| Package | Compatible With | Notes |
|---|---|---|
| flutter_riverpod ^3.3.1 | Flutter >=3.41.0, Dart >=3.7 | Pre-3.41 Flutter stable had a transitive analyzer conflict. Resolved in Flutter 3.41.1. Use current stable (3.41.2). |
| drift ^2.32.0 + drift_dev ^2.32.0 | Build-runner ^2.12.2 | drift and drift_dev versions must match exactly. |
| riverpod_generator ^4.0.3 | riverpod_annotation ^4.0.2 | Generator and annotation major versions must match (both 4.x). |
| freezed ^3.2.5 | freezed_annotation ^3.1.0 | Major versions must match (both 3.x). |
| flutter_local_notifications ^21.0.0 | Android API 24+ (Android 7.0+) | Minimum API level 24. Requires RECEIVE_BOOT_COMPLETED permission in AndroidManifest.xml and core library desugaring in build.gradle.kts. |
| flex_color_scheme ^8.4.0 | Flutter >=3.x, Dart >=3.x | M3 enabled by default in v8+. No additional configuration needed. |
Sources
- pub.dev/packages/flutter_riverpod — version 3.3.1 verified directly
- pub.dev/packages/riverpod_generator — version 4.0.3 verified directly
- pub.dev/packages/riverpod_annotation — version 4.0.2 verified directly
- riverpod.dev/docs/whats_new — Riverpod 3.0 feature list
- riverpod.dev/docs/3.0_migration — breaking changes guide
- pub.dev/packages/drift — version 2.32.0 verified directly
- pub.dev/packages/drift_flutter — version 0.3.0 verified directly
- drift.simonbinder.eu/setup — official Drift setup guide
- pub.dev/packages/go_router — version 17.1.0 verified directly
- pub.dev/packages/flutter_local_notifications — version 21.0.0 verified directly
- pub.dev/packages/freezed — version 3.2.5 verified directly
- pub.dev/packages/freezed_annotation — version 3.1.0 verified directly
- pub.dev/packages/flex_color_scheme — version 8.4.0 verified directly
- pub.dev/packages/timezone — version 0.11.0 verified directly
- pub.dev/packages/build_runner — version 2.12.2 verified directly
- pub.dev/packages/flutter_lints — version 6.0.0 verified directly
- github.com/rrousselGit/riverpod/issues/4676 — Riverpod 3.2+/stable channel compatibility; resolved in Flutter 3.41.1 (MEDIUM confidence)
- docs.flutter.dev/release/archive — Flutter 3.41 current stable confirmed
- docs.flexcolorscheme.com — M3 legacy color sync coverage (MEDIUM confidence, official docs)
Stack research for: Local-first Flutter household chore management app (HouseHoldKeaper) Researched: 2026-03-15