Skip to content

@tank/flutter-dev

1.0.0

Description

Production Flutter and Dart development patterns. Covers widget architecture, state management (Riverpod, BLoC, Provider), navigation (GoRouter), Dart 3 patterns, layouts, testing, performance profiling, platform channels, and deployment.

Triggered by

flutterdartriverpodblocgo_routerwidget test
Download
Verified
tank install @tank/flutter-dev

Flutter Development

Core Philosophy

  1. Composition over inheritance — Build complex UIs by combining small, focused widgets. Extract widgets into separate classes instead of adding parameters to bloated ones.
  2. Immutable widget tree, mutable state tree — Widgets are throwaway configuration objects. The Element tree persists across frames and drives performance. Understand this distinction to avoid unnecessary rebuilds.
  3. Push state down, lift state up — Keep state as close to where it is consumed as possible. Lift only when siblings need to share it. Use Riverpod or BLoC for app-level state, setState for ephemeral UI state.
  4. Declarative navigation — Use GoRouter for URL-based, declarative routing. Imperative Navigator.push breaks deep linking, web URLs, and state restoration.
  5. Test the widget, not the framework — Write widget tests that verify behavior, not Flutter internals. Use golden tests for visual regression. Test state management in isolation with unit tests.

Quick-Start: Common Problems

"Which state management should I use?"

App TypeRecommended
New app, any sizeRiverpod (NotifierProvider + AsyncNotifierProvider)
Existing app with ProviderMigrate incrementally to Riverpod
Enterprise, strict event auditBLoC (event-driven, traceable)
Simple prototype / MVPRiverpod or even plain setState
Legacy app with ChangeNotifierProvider package (maintain, don't rewrite)
-> See references/state-management.md

"My widget rebuilds too often"

  1. Mark constructors const — enables framework-level rebuild skipping
  2. Extract subtrees that depend on different state into separate widgets
  3. Use select (Riverpod) or BlocSelector (BLoC) to watch specific fields
  4. Add RepaintBoundary around expensive paint operations
  5. Profile with Flutter DevTools Widget Rebuild Tracker -> See references/performance-deployment.md

"How do I structure navigation with tabs and auth?"

  1. Use GoRouter with StatefulShellRoute for persistent tab navigation
  2. Add redirect for auth guards — check auth state, redirect to /login
  3. Use ShellRoute for shared scaffolds (AppBar, Drawer)
  4. Handle deep links by defining path parameters: /user/:id -> See references/navigation-routing.md

"How do I test a widget that depends on Riverpod/BLoC?"

  1. Riverpod: wrap with ProviderScope, override providers with mock values
  2. BLoC: use BlocProvider.value with a mock Bloc/Cubit
  3. Use pumpWidget + pumpAndSettle for async rendering
  4. Golden tests: expectLater(find.byType(X), matchesGoldenFile('x.png')) -> See references/testing.md

"When do I use which Dart pattern?"

  1. Sealed classes for state unions (loading/data/error)
  2. Records for returning multiple values without creating a class
  3. Pattern matching with switch expressions for exhaustive handling
  4. Extensions for adding methods to types you do not own
  5. Freezed for data classes with copyWith, equality, JSON serialization -> See references/dart-patterns.md

Decision Trees

Widget Type Selection

SignalWidget Type
No mutable state, pure UIStatelessWidget (use const)
Ephemeral UI state (animation, form input)StatefulWidget + setState
State shared across subtree without passing propsInheritedWidget (or Riverpod)
Needs TickerProvider for animationsStatefulWidget with SingleTickerProviderStateMixin

Layout Widget Selection

NeedWidget
Horizontal or vertical list of childrenRow / Column (Flex)
Overlapping childrenStack + Positioned
Scrollable list of unknown lengthListView.builder
Scrollable with mixed content (headers, grids, lists)CustomScrollView + Sliver*
Responsive sizingLayoutBuilder or MediaQuery
Adaptive per platform (Material vs Cupertino)Platform checks + .adaptive constructors

Key Type Selection

ScenarioKey Type
Reorder items in a listValueKey(item.id)
Preserve state when widget moves in treeGlobalKey (use sparingly)
Force rebuild when data identity changesValueKey(dataObject)
Ensure unique key for generated widgetsUniqueKey()

Reference Index

FileContents
references/widget-architecture.mdWidget tree, Element tree, BuildContext, Keys, lifecycle methods, composition patterns, RenderObject basics
references/state-management.mdRiverpod (all provider types, ref patterns, testing), BLoC/Cubit, Provider, selection decision framework
references/navigation-routing.mdGoRouter setup, ShellRoute, StatefulShellRoute, redirect guards, deep linking, path/query parameters, nested navigation
references/dart-patterns.mdNull safety, sealed classes, records, pattern matching, extensions, mixins, Freezed, code generation
references/layouts-responsive.mdFlex system, Stack, Slivers, LayoutBuilder, MediaQuery, breakpoints, Material 3, Cupertino, adaptive design
references/testing.mdWidget tests, integration tests, golden tests, Riverpod/BLoC test patterns, mocking with Mocktail
references/performance-deployment.mdDevTools profiling, const optimization, RepaintBoundary, tree shaking, flavors, CI/CD, Fastlane, app store submission

Command Palette

Search skills, docs, and navigate Tank