30 KiB
Phase 1: Foundation - Research
Researched: 2026-03-15 Domain: Flutter app scaffolding, Drift SQLite, Riverpod 3 state management, Material 3 theming, ARB localization Confidence: HIGH
Summary
Phase 1 establishes the foundational architecture for a greenfield Flutter app targeting Android. The core technologies are well-documented and stable: Flutter 3.41.2 (current stable), Riverpod 3.3 with code generation, Drift 2.32 for SQLite persistence, and Flutter's built-in gen_l10n tooling for ARB-based localization. All of these are mature, actively maintained, and have clear official documentation.
The primary risk areas are: (1) Riverpod 3's new analysis_server_plugin-based lint setup replacing the older custom_lint approach, which may have IDE integration quirks, and (2) getting the Drift make-migrations workflow right from the start since retrofitting it later risks data loss. The developer is new to Drift, so the plan should include explicit verification steps for the migration workflow.
Primary recommendation: Scaffold with flutter create, add all dependencies in one pass, establish code generation (build_runner) and the Drift migration pipeline before writing any feature code. Use go_router with StatefulShellRoute.indexedStack for bottom navigation with preserved tab state.
<user_constraints>
User Constraints (from CONTEXT.md)
Locked Decisions
- Color palette & theme: Sage & stone -- muted sage green primary, warm stone/beige surfaces, slate blue accents. Color-shy: mostly neutral surfaces, color only on key interactive elements. Light mode: warm stone/beige surface tones. Dark mode: warm charcoal-brown backgrounds (not pure #121212 black). Use M3 color system with ColorScheme.fromSeed, tuning the seed and surface tints.
- Navigation & tabs: Thematic icons (checklist/clipboard for Home, door for Rooms, sliders for Settings). German labels from ARB files: "Ubersicht", "Raume", "Einstellungen". Default tab: Home. Active tab style: standard Material 3 behavior with sage green palette.
- Placeholder screens: Playful & light tone with emoji-friendly German text. Pattern: Material icon + playful message + action button. Home empty state guides user to Rooms tab. Rooms empty state encourages creating first room. All text from ARB files.
- Settings screen: Working theme switcher (System/Hell/Dunkel) + About section (app name, version, tagline). Grouped with section headers "Darstellung" and "Uber". Tagline: "Dein Haushalt, entspannt organisiert." Language setting hidden until v1.1.
Claude's Discretion
- Theme picker widget style (segmented button, dropdown, or bottom sheet -- pick best M3 pattern)
- Exact icon choices for thematic tab icons (from Material Icons set)
- Loading skeleton and transition animations
- Exact spacing, typography scale, and component sizing
- Error state designs (database/initialization errors)
Deferred Ideas (OUT OF SCOPE)
None -- discussion stayed within phase scope
</user_constraints>
<phase_requirements>
Phase Requirements
| ID | Description | Research Support |
|---|---|---|
| FOUND-01 | App uses Drift for local SQLite storage with proper schema migration workflow | Drift 2.32 setup with drift_flutter, make-migrations command, build.yaml config, stepByStep migration strategy, schema versioning and test generation |
| FOUND-02 | App uses Riverpod 3 for state management with code generation | flutter_riverpod 3.3.x + riverpod_annotation 4.0.x + riverpod_generator 4.0.x with @riverpod annotation and build_runner |
| FOUND-03 | App uses localization infrastructure (ARB files + AppLocalizations) with German locale | l10n.yaml with template-arb-file: app_de.arb, flutter_localizations SDK dependency, generate: true in pubspec |
| FOUND-04 | Bottom navigation with tabs: Home (Daily Plan), Rooms, Settings | go_router 17.x with StatefulShellRoute.indexedStack for preserved tab navigation state, NavigationBar (M3 widget) |
| THEME-01 | App supports light and dark themes, following the system setting by default | ThemeMode.system default, ColorScheme.fromSeed with brightness variants, Riverpod provider for theme preference persistence |
| THEME-02 | App uses a calm Material 3 palette with muted greens, warm grays, and gentle blues | Sage green seed color with DynamicSchemeVariant.tonalSpot, surface color overrides via .copyWith() for warm stone/charcoal tones |
</phase_requirements>
Standard Stack
Core
| Library | Version | Purpose | Why Standard |
|---|---|---|---|
| flutter | 3.41.2 | UI framework | Current stable, required by Riverpod 3.3 |
| flutter_riverpod | ^3.3.0 | State management (Flutter bindings) | Community standard for new Flutter projects in 2026, compile-time safety |
| riverpod_annotation | ^4.0.2 | @riverpod annotation for code generation |
Required for Riverpod 3 code generation workflow |
| drift | ^2.32.0 | Reactive SQLite ORM | Type-safe queries, migration tooling, compile-time validation |
| drift_flutter | ^0.3.0 | Flutter-specific database opener | Simplifies platform-specific SQLite setup |
| go_router | ^17.1.0 | Declarative routing | Flutter team maintained, StatefulShellRoute for bottom nav |
Supporting
| Library | Version | Purpose | When to Use |
|---|---|---|---|
| riverpod_generator | ^4.0.3 | Code gen for providers (dev dep) | Always -- generates provider boilerplate from @riverpod annotations |
| drift_dev | ^2.32.0 | Code gen for Drift tables (dev dep) | Always -- generates typed database code and migration helpers |
| build_runner | ^2.11.1 | Runs code generators (dev dep) | Always -- orchestrates riverpod_generator and drift_dev |
| riverpod_lint | ^3.1.3 | Lint rules for Riverpod (dev dep) | Always -- catches ref.watch outside build() at analysis time |
| path_provider | ^2.1.5 | Platform-specific file paths | Used by drift_flutter for database file location |
| flutter_localizations | SDK | Material/Cupertino l10n delegates | Required for ARB-based localization |
| intl | any | Internationalization utilities | Required by gen_l10n for date/number formatting |
| shared_preferences | ^2.3.0 | Key-value persistence | Theme mode preference persistence across app restarts |
Alternatives Considered
| Instead of | Could Use | Tradeoff |
|---|---|---|
| go_router | Auto-route | go_router is Flutter team maintained, has first-class StatefulShellRoute support; auto_route adds more codegen |
| shared_preferences (theme) | Drift table | Overkill for a single enum value; shared_preferences is simpler for settings |
| ColorScheme.fromSeed | flex_seed_scheme | flex_seed_scheme offers multi-seed colors and more control; but fromSeed with .copyWith() is sufficient for this palette and avoids extra dependency |
Installation
flutter create household_keeper --org com.jlmak --platforms android
cd household_keeper
flutter pub add flutter_riverpod riverpod_annotation drift drift_flutter go_router path_provider shared_preferences
flutter pub add -d riverpod_generator drift_dev build_runner riverpod_lint
Note: flutter_localizations and intl are added manually to pubspec.yaml under the flutter_localizations: sdk: flutter pattern.
Architecture Patterns
Recommended Project Structure
lib/
├── app.dart # MaterialApp.router with theme, localization, ProviderScope
├── main.dart # Entry point, ProviderScope wrapper
├── core/
│ ├── database/
│ │ ├── database.dart # @DriftDatabase class, schema version, migration strategy
│ │ ├── database.g.dart # Generated Drift code
│ │ └── database.steps.dart # Generated migration steps
│ ├── router/
│ │ └── router.dart # GoRouter config with StatefulShellRoute
│ ├── theme/
│ │ ├── app_theme.dart # Light/dark ThemeData with ColorScheme.fromSeed
│ │ └── theme_provider.dart # Riverpod provider for ThemeMode
│ └── providers/
│ └── database_provider.dart # Riverpod provider exposing AppDatabase
├── features/
│ ├── home/
│ │ └── presentation/
│ │ └── home_screen.dart # Placeholder with empty state
│ ├── rooms/
│ │ └── presentation/
│ │ └── rooms_screen.dart # Placeholder with empty state
│ └── settings/
│ └── presentation/
│ └── settings_screen.dart # Theme switcher + About section
├── l10n/
│ └── app_de.arb # German strings (template file)
└── shell/
└── app_shell.dart # Scaffold with NavigationBar, receives StatefulNavigationShell
Pattern 1: Riverpod Provider with Code Generation
What: Define providers using @riverpod annotation, let build_runner generate the boilerplate
When to use: All state management -- no manual provider declarations
Example:
// Source: https://riverpod.dev/docs/introduction/getting_started
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'theme_provider.g.dart';
@riverpod
class ThemeNotifier extends _$ThemeNotifier {
@override
ThemeMode build() {
// Read persisted preference, default to system
return ThemeMode.system;
}
void setThemeMode(ThemeMode mode) {
state = mode;
// Persist to shared_preferences
}
}
Pattern 2: StatefulShellRoute for Bottom Navigation
What: go_router's StatefulShellRoute.indexedStack preserves each tab's navigation stack independently
When to use: Bottom navigation with independent tab histories
Example:
// Source: https://pub.dev/packages/go_router
final router = GoRouter(
routes: [
StatefulShellRoute.indexedStack(
builder: (context, state, navigationShell) {
return AppShell(navigationShell: navigationShell);
},
branches: [
StatefulShellBranch(routes: [
GoRoute(path: '/', builder: (context, state) => const HomeScreen()),
]),
StatefulShellBranch(routes: [
GoRoute(path: '/rooms', builder: (context, state) => const RoomsScreen()),
]),
StatefulShellBranch(routes: [
GoRoute(path: '/settings', builder: (context, state) => const SettingsScreen()),
]),
],
),
],
);
Pattern 3: Drift Database with DAO Separation
What: Each logical domain gets its own DAO class annotated with @DriftAccessor
When to use: From Phase 1 onward -- even with an empty schema, establish the pattern
Example:
// Source: https://drift.simonbinder.eu/dart_api/daos/
@DriftDatabase(tables: [/* tables added in Phase 2 */], daos: [/* DAOs added in Phase 2 */])
class AppDatabase extends _$AppDatabase {
AppDatabase([QueryExecutor? executor]) : super(executor ?? _openConnection());
@override
int get schemaVersion => 1;
static QueryExecutor _openConnection() {
return driftDatabase(
name: 'household_keeper',
native: const DriftNativeOptions(
databaseDirectory: getApplicationSupportDirectory,
),
);
}
}
Pattern 4: ColorScheme.fromSeed with Surface Overrides
What: Generate a harmonious M3 color scheme from a sage green seed, then override surface colors for warmth When to use: Theme definition Example:
// Source: https://api.flutter.dev/flutter/material/ColorScheme/ColorScheme.fromSeed.html
ColorScheme _lightScheme() {
return ColorScheme.fromSeed(
seedColor: const Color(0xFF7A9A6D), // Sage green
brightness: Brightness.light,
dynamicSchemeVariant: DynamicSchemeVariant.tonalSpot,
).copyWith(
surface: const Color(0xFFF5F0E8), // Warm stone
surfaceContainerLowest: const Color(0xFFFAF7F2),
surfaceContainerLow: const Color(0xFFF2EDE4),
surfaceContainer: const Color(0xFFEDE7DC),
surfaceContainerHigh: const Color(0xFFE7E0D5),
surfaceContainerHighest: const Color(0xFFE0D9CE),
);
}
ColorScheme _darkScheme() {
return ColorScheme.fromSeed(
seedColor: const Color(0xFF7A9A6D), // Same sage green seed
brightness: Brightness.dark,
dynamicSchemeVariant: DynamicSchemeVariant.tonalSpot,
).copyWith(
surface: const Color(0xFF2A2520), // Warm charcoal-brown (not #121212)
surfaceContainerLowest: const Color(0xFF1E1A16),
surfaceContainerLow: const Color(0xFF322D27),
surfaceContainer: const Color(0xFF3A342E),
surfaceContainerHigh: const Color(0xFF433D36),
surfaceContainerHighest: const Color(0xFF4D463F),
);
}
Anti-Patterns to Avoid
- Hardcoding strings in Dart: All user-visible text MUST come from ARB files via
AppLocalizations.of(context)!.keyName. Even placeholder screen text. - Manual provider declarations: Always use
@riverpodannotation + code generation. Never writeStateProvider,StateNotifierProvider, orChangeNotifierProvider-- these are legacy in Riverpod 3. - Skipping make-migrations on initial schema: Run
dart run drift_dev make-migrationsimmediately after creating the database class withschemaVersion => 1, BEFORE making any changes. This captures the baseline schema. - Using Navigator.push with go_router: Use
context.go()andcontext.push()from go_router. Never mix Navigator API with GoRouter. - Sharing ProviderContainer between tests: Each test must get its own
ProviderContainerorProviderScope.
Don't Hand-Roll
| Problem | Don't Build | Use Instead | Why |
|---|---|---|---|
| Database migrations | Manual SQL ALTER statements | Drift make-migrations + stepByStep |
Drift generates type-safe migration steps, auto-generates tests, catches schema drift at compile time |
| Provider boilerplate | Manual StateNotifierProvider / Provider declarations |
@riverpod + riverpod_generator |
Eliminates AutoDispose/Family variants, unified Ref, compile-time error detection |
| Color scheme harmony | Manual hex color picking for all 30+ ColorScheme roles | ColorScheme.fromSeed() + .copyWith() |
Algorithm ensures contrast ratios, accessibility compliance, and tonal harmony |
| Route management | Manual Navigator.push/pop with IndexedStack | go_router StatefulShellRoute |
Handles back button, deep links, tab state preservation, URL-based navigation |
| Localization code | Manual Map<String, String> lookups | gen_l10n with ARB files |
Type-safe access via AppLocalizations.of(context)!.key, compile-time key validation |
| Theme mode persistence | Manual file I/O for settings | shared_preferences |
Handles platform-specific key-value storage, async initialization, type safety |
Key insight: This phase is infrastructure-heavy. Every "hand-rolled" solution here would need to be replaced later when the real features arrive in Phases 2-4. Using the standard tooling from day 1 prevents a rewrite.
Common Pitfalls
Pitfall 1: Forgetting to Run make-migrations Before First Schema Change
What goes wrong: You define tables, change them, bump schemaVersion to 2, but never captured schema version 1. Drift cannot generate the from1To2 migration step.
Why it happens: Developer creates tables and iterates on them during initial development before thinking about migrations.
How to avoid: Run dart run drift_dev make-migrations immediately after defining the initial database class with schemaVersion => 1 and zero tables. This captures the empty schema as version 1. Then add tables and bump to version 2.
Warning signs: make-migrations errors about missing schema files in drift_schemas/.
Pitfall 2: Riverpod Code Generation Not Running
What goes wrong: .g.dart files are missing or stale, causing compilation errors referencing _$ClassName.
Why it happens: Developer forgets to run dart run build_runner build or the watcher (build_runner watch) is not running.
How to avoid: Start development with dart run build_runner watch -d in a terminal. The -d flag deletes conflicting outputs. Add a note in the project README.
Warning signs: Target of URI hasn't been generated errors in the IDE.
Pitfall 3: riverpod_lint Not Showing in IDE
What goes wrong: Lint rules like ref.watch outside build don't appear as analysis errors in VS Code / Android Studio.
Why it happens: Riverpod 3 uses analysis_server_plugin instead of custom_lint. The IDE may need a restart of the Dart analysis server, or the analysis_options.yaml is misconfigured.
How to avoid: Verify by running dart analyze from the terminal -- if lints appear there but not in the IDE, restart the analysis server. Ensure analysis_options.yaml has plugins: riverpod_lint: ^3.1.3 (not the old analyzer: plugins: - custom_lint format).
Warning signs: No Riverpod-specific warnings anywhere in the project. Run dart analyze to verify.
Pitfall 4: ColorScheme.fromSeed Ignoring Surface Overrides
What goes wrong: You pass surface: to ColorScheme.fromSeed() constructor but the surface color doesn't change.
Why it happens: Known Flutter issue -- some color role parameters in fromSeed() constructor may be ignored by the algorithm.
How to avoid: Always use .copyWith() AFTER ColorScheme.fromSeed() to override surface colors. This reliably works.
Warning signs: Surfaces appear as cool gray instead of warm stone/beige.
Pitfall 5: ARB Template File Must Be the Source Language
What goes wrong: Code generation fails or produces incorrect AppLocalizations when template file doesn't match supported locale.
Why it happens: The template-arb-file in l10n.yaml must correspond to a supported locale.
How to avoid: Use app_de.arb as the template file since German is the only (and source) language. Set template-arb-file: app_de.arb in l10n.yaml.
Warning signs: gen-l10n errors about missing template or unsupported locale.
Pitfall 6: ThemeMode.system as Default Without Persistence
What goes wrong: User selects "Hell" (light) in settings, restarts app, and it reverts to system theme.
Why it happens: ThemeMode is stored only in Riverpod state (memory), not persisted to disk.
How to avoid: Use shared_preferences to persist the ThemeMode enum value. On app start, read persisted value; default to ThemeMode.system if no value stored.
Warning signs: Theme selection doesn't survive app restart.
Code Examples
Verified patterns from official sources:
l10n.yaml Configuration (German-only)
# Source: https://docs.flutter.dev/ui/internationalization
arb-dir: lib/l10n
template-arb-file: app_de.arb
output-localization-file: app_localizations.dart
nullable-getter: false
pubspec.yaml Localization Dependencies
# Source: https://docs.flutter.dev/ui/internationalization
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: any
flutter:
generate: true
MaterialApp.router Setup
// Source: https://docs.flutter.dev/ui/internationalization + https://riverpod.dev
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class App extends ConsumerWidget {
const App({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final themeMode = ref.watch(themeNotifierProvider);
return MaterialApp.router(
routerConfig: router,
theme: ThemeData(colorScheme: lightColorScheme, useMaterial3: true),
darkTheme: ThemeData(colorScheme: darkColorScheme, useMaterial3: true),
themeMode: themeMode,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: const [Locale('de')],
locale: const Locale('de'),
);
}
}
SegmentedButton Theme Switcher (Recommended for Claude's Discretion)
// Source: https://api.flutter.dev/flutter/material/SegmentedButton-class.html
// Recommendation: SegmentedButton is the best M3 pattern for 3-option single-select
SegmentedButton<ThemeMode>(
segments: [
ButtonSegment(
value: ThemeMode.system,
label: Text(l10n.themeSystem), // "System"
icon: const Icon(Icons.settings_suggest_outlined),
),
ButtonSegment(
value: ThemeMode.light,
label: Text(l10n.themeLight), // "Hell"
icon: const Icon(Icons.light_mode_outlined),
),
ButtonSegment(
value: ThemeMode.dark,
label: Text(l10n.themeDark), // "Dunkel"
icon: const Icon(Icons.dark_mode_outlined),
),
],
selected: {currentThemeMode},
onSelectionChanged: (selection) {
ref.read(themeNotifierProvider.notifier).setThemeMode(selection.first);
},
)
Drift build.yaml Configuration
# Source: https://drift.simonbinder.eu/migrations/
targets:
$default:
builders:
drift_dev:
options:
databases:
household_keeper: lib/core/database/database.dart
sql:
dialect: sqlite
options:
version: "3.38"
analysis_options.yaml with riverpod_lint
# Source: https://riverpod.dev/docs/introduction/getting_started
include: package:flutter_lints/flutter.yaml
plugins:
riverpod_lint: ^3.1.3
AppShell with NavigationBar
// Source: https://codewithandrea.com/articles/flutter-bottom-navigation-bar-nested-routes-gorouter/
class AppShell extends StatelessWidget {
final StatefulNavigationShell navigationShell;
const AppShell({super.key, required this.navigationShell});
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context);
return Scaffold(
body: navigationShell,
bottomNavigationBar: NavigationBar(
selectedIndex: navigationShell.currentIndex,
onDestinationSelected: (index) {
navigationShell.goBranch(
index,
initialLocation: index == navigationShell.currentIndex,
);
},
destinations: [
NavigationDestination(
icon: const Icon(Icons.checklist_outlined),
selectedIcon: const Icon(Icons.checklist),
label: l10n.tabHome, // "Ubersicht"
),
NavigationDestination(
icon: const Icon(Icons.door_front_door_outlined),
selectedIcon: const Icon(Icons.door_front_door),
label: l10n.tabRooms, // "Raume"
),
NavigationDestination(
icon: const Icon(Icons.tune_outlined),
selectedIcon: const Icon(Icons.tune),
label: l10n.tabSettings, // "Einstellungen"
),
],
),
);
}
}
State of the Art
| Old Approach | Current Approach | When Changed | Impact |
|---|---|---|---|
StateNotifierProvider / ChangeNotifierProvider |
@riverpod annotation + code generation |
Riverpod 3.0 (2025) | Legacy APIs still work but are deprecated; all new code should use code generation |
custom_lint for riverpod_lint |
analysis_server_plugin |
Riverpod 3.0 (2025) | Setup via plugins: in analysis_options.yaml instead of analyzer: plugins: |
Ref<T> with generic parameter |
Unified Ref (no generic) |
Riverpod 3.0 (2025) | Simplified API -- one Ref type for all providers |
useMaterial3: true flag needed |
Material 3 is default | Flutter 3.16+ (2023) | No need to explicitly enable M3 |
background / onBackground color roles |
surface / onSurface |
Flutter 3.22+ (2024) | Old roles deprecated; use new surface container hierarchy |
| Manual drift schema dumps | dart run drift_dev make-migrations |
Drift 2.x (2024) | Automated step-by-step migration file generation and test scaffolding |
Deprecated/outdated:
StateProvider,StateNotifierProvider,ChangeNotifierProvider: Legacy in Riverpod 3 -- use@riverpodannotationAutoDisposeNotifiervsNotifierdistinction: Unified in Riverpod 3 -- just useNotifierColorScheme.background/ColorScheme.onBackground: Deprecated -- usesurface/onSurfaceColorScheme.surfaceVariant: Deprecated -- usesurfaceContainerHighest
Open Questions
-
Exact sage green hex value for seed color
- What we know: The palette should evoke "a calm kitchen with natural materials" -- sage green primary, slate blue accents
- What's unclear: The exact hex value that produces the best M3 tonal palette when run through
fromSeed - Recommendation: Start with
Color(0xFF7A9A6D)(muted sage) and iterate visually. ThedynamicSchemeVariant: DynamicSchemeVariant.tonalSpotwill automatically produce muted tones. Fine-tune surface overrides for warmth.
-
Riverpod 3 package compatibility with Flutter stable channel
- What we know: Riverpod docs specify
sdk: ^3.7.0andflutter: ">=3.0.0". Some reports mention beta channel needed for latestjson_serializablecompatibility. - What's unclear: Whether
flutter_riverpod: ^3.3.0works cleanly on Flutter 3.41.2 stable without issues - Recommendation: Run
flutter pub getearly in the scaffolding wave. If version resolution fails, useflutter_riverpod: ^3.1.0as fallback.
- What we know: Riverpod docs specify
-
Drift make-migrations with an empty initial schema
- What we know: The docs say to run
make-migrationsbefore making changes. In Phase 1, we may have zero tables (tables come in Phase 2). - What's unclear: Whether
make-migrationsworks with an empty database (no tables) - Recommendation: Define the database class with
schemaVersion => 1and at minimum one placeholder table or zero tables, then runmake-migrations. If it fails on empty, add a placeholderAppSettingstable with a single column.
- What we know: The docs say to run
Validation Architecture
Test Framework
| Property | Value |
|---|---|
| Framework | flutter_test (bundled with Flutter SDK) |
| Config file | none -- see Wave 0 |
| Quick run command | flutter test |
| Full suite command | flutter test --coverage |
Phase Requirements to Test Map
| Req ID | Behavior | Test Type | Automated Command | File Exists? |
|---|---|---|---|---|
| FOUND-01 | Drift database opens with schemaVersion 1, make-migrations runs | unit + smoke | flutter test test/core/database/database_test.dart -x |
No -- Wave 0 |
| FOUND-02 | Riverpod providers generate correctly, riverpod_lint active | smoke | dart analyze |
No -- Wave 0 |
| FOUND-03 | AppLocalizations.of(context) returns German strings, no hardcoded text | widget | flutter test test/l10n/localization_test.dart -x |
No -- Wave 0 |
| FOUND-04 | Bottom nav shows 3 tabs, tapping switches content | widget | flutter test test/shell/app_shell_test.dart -x |
No -- Wave 0 |
| THEME-01 | Light/dark themes switch correctly, system default works | widget | flutter test test/core/theme/theme_test.dart -x |
No -- Wave 0 |
| THEME-02 | Color scheme uses sage green seed, surfaces are warm-toned | unit | flutter test test/core/theme/color_scheme_test.dart -x |
No -- Wave 0 |
Sampling Rate
- Per task commit:
flutter test - Per wave merge:
flutter test --coverage - Phase gate: Full suite green +
dart analyzeclean (zero riverpod_lint issues)
Wave 0 Gaps
test/core/database/database_test.dart-- covers FOUND-01 (database opens, schema version correct)test/l10n/localization_test.dart-- covers FOUND-03 (German strings load from ARB)test/shell/app_shell_test.dart-- covers FOUND-04 (navigation bar renders 3 tabs)test/core/theme/theme_test.dart-- covers THEME-01 (light/dark/system switching)test/core/theme/color_scheme_test.dart-- covers THEME-02 (sage green seed, warm surfaces)- Drift migration test scaffolding via
dart run drift_dev make-migrations(auto-generated)
Sources
Primary (HIGH confidence)
- Riverpod official docs - getting started, package versions, code generation setup, lint setup
- Drift official docs - setup, migration workflow, make-migrations, DAOs
- Flutter official docs - ARB localization setup, l10n.yaml
- Flutter API reference - ColorScheme.fromSeed, DynamicSchemeVariant, SegmentedButton
- pub.dev/packages/drift - version 2.32.0 verified
- pub.dev/packages/flutter_riverpod - version 3.3.1 verified
- pub.dev/packages/go_router - version 17.1.0 verified
- pub.dev/packages/riverpod_lint - version 3.1.3, 14 lint rules documented
Secondary (MEDIUM confidence)
- Flutter 3.41 blog post - Flutter 3.41.2 current stable confirmed
- CodeWithAndrea go_router tutorial - StatefulShellRoute.indexedStack pattern
- Drift migrations docs - make-migrations workflow, stepByStep pattern
- DynamicSchemeVariant API - tonalSpot vs fidelity behavior
Tertiary (LOW confidence)
- Exact surface color hex values for warm stone/charcoal -- these are illustrative starting points, need visual iteration
- Riverpod 3.3 compatibility with Flutter stable -- most reports confirm it works, but a few mention beta channel needed
Metadata
Confidence breakdown:
- Standard stack: HIGH - all packages verified on pub.dev with current versions, official docs consulted
- Architecture: HIGH - patterns drawn from official go_router and Riverpod documentation, well-established in community
- Pitfalls: HIGH - documented issues verified across multiple sources (GitHub issues, official docs, community reports)
- Color palette: MEDIUM - hex values are starting points; M3 algorithm behavior verified but exact visual output requires iteration
- riverpod_lint setup: MEDIUM - new analysis_server_plugin approach is documented but IDE integration may have quirks
Research date: 2026-03-15 Valid until: 2026-04-15 (30 days -- stable ecosystem, no major releases expected before Flutter 3.44 in May)