Flutter Expert
Senior mobile engineer building high-performance cross-platform applications with Flutter 3 and Dart.
When to Use This Skill
- Building cross-platform Flutter applications
- Implementing state management (Riverpod, Bloc)
- Setting up navigation with GoRouter
- Creating custom widgets and animations
- Optimizing Flutter performance
- Platform-specific implementations
Core Workflow
- Setup — Scaffold project, add dependencies (
flutter pub get), configure routing
- State — Define Riverpod providers or Bloc/Cubit classes; verify with
flutter analyze
- If
flutter analyze reports issues: fix all lints and warnings before proceeding; re-run until clean
- Widgets — Build reusable, const-optimized components; run
flutter test after each feature
- If tests fail: inspect widget tree with Flutter DevTools, fix failing assertions, re-run
flutter test
- Test — Write widget and integration tests; confirm with
flutter test --coverage
- If coverage drops or tests fail: identify untested branches, add targeted tests, re-run before merging
- Optimize — Profile with Flutter DevTools (
flutter run --profile), eliminate jank, reduce rebuilds
- If jank persists: check rebuild counts in the Performance overlay, isolate expensive
build() calls, apply const or move state closer to consumers
Reference Guide
Load detailed guidance based on context:
| Topic |
Reference |
Load When |
| Riverpod |
references/riverpod-state.md |
State management, providers, notifiers |
| Bloc |
references/bloc-state.md |
Bloc, Cubit, event-driven state, complex business logic |
| GoRouter |
references/gorouter-navigation.md |
Navigation, routing, deep linking |
| Widgets |
references/widget-patterns.md |
Building UI components, const optimization |
| Structure |
references/project-structure.md |
Setting up project, architecture |
| Performance |
references/performance.md |
Optimization, profiling, jank fixes |
Code Examples
Riverpod Provider + ConsumerWidget (correct pattern)
// provider definition
final counterProvider = StateNotifierProvider<CounterNotifier, int>(
(ref) => CounterNotifier(),
);
class CounterNotifier extends StateNotifier<int> {
CounterNotifier() : super(0);
void increment() => state = state + 1; // new instance, never mutate
}
// consuming widget — use ConsumerWidget, not StatefulWidget
class CounterView extends ConsumerWidget {
const CounterView({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Text('$count');
}
}
Before / After — State Management
// ❌ WRONG: app-wide state in setState
class _BadCounterState extends State<BadCounter> {
int _count = 0;
void _inc() => setState(() => _count++); // causes full subtree rebuild
}
// ✅ CORRECT: scoped Riverpod consumer
class GoodCounter extends ConsumerWidget {
const GoodCounter({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return IconButton(
onPressed: () => ref.read(counterProvider.notifier).increment(),
icon: const Icon(Icons.add), // const on static widgets
);
}
}
Constraints
MUST DO
- Use
const constructors wherever possible
- Implement proper keys for lists
- Use
Consumer/ConsumerWidget for state (not StatefulWidget)
- Follow Material/Cupertino design guidelines
- Profile with DevTools, fix jank
- Test widgets with
flutter_test
MUST NOT DO
- Build widgets inside
build() method
- Mutate state directly (always create new instances)
- Use
setState for app-wide state
- Skip
const on static widgets
- Ignore platform-specific behavior
- Block UI thread with heavy computation (use
compute())
Troubleshooting Common Failures
| Symptom |
Likely Cause |
Recovery |
flutter analyze errors |
Unresolved imports, missing const, type mismatches |
Fix flagged lines; run flutter pub get if imports are missing |
| Widget test assertion failures |
Widget tree mismatch or async state not settled |
Use tester.pumpAndSettle() after state changes; verify finder selectors |
| Build fails after adding package |
Incompatible dependency version |
Run flutter pub upgrade --major-versions; check pub.dev compatibility |
| Jank / dropped frames |
Expensive build() calls, uncached widgets, heavy main-thread work |
Use RepaintBoundary, move heavy work to compute(), add const |
| Hot reload not reflecting changes |
State held in StateNotifier not reset |
Use hot restart (R in terminal) to reset full app state |
Output Templates
When implementing Flutter features, provide:
- Widget code with proper
const usage
- Provider/Bloc definitions
- Route configuration if needed
- Test file structure
1---2name: flutter-expert3description: Use when building cross-platform applications with Flutter 3+ and Dart. Invoke for widget development, Riverpod/Bloc state management, GoRouter navigation, platform-specific implementations, performance optimization.4license: MIT5---67# Flutter Expert89Senior mobile engineer building high-performance cross-platform applications with Flutter 3 and Dart.1011## When to Use This Skill1213- Building cross-platform Flutter applications14- Implementing state management (Riverpod, Bloc)15- Setting up navigation with GoRouter16- Creating custom widgets and animations17- Optimizing Flutter performance18- Platform-specific implementations1920## Core Workflow21221. **Setup** — Scaffold project, add dependencies (`flutter pub get`), configure routing232. **State** — Define Riverpod providers or Bloc/Cubit classes; verify with `flutter analyze`24 - If `flutter analyze` reports issues: fix all lints and warnings before proceeding; re-run until clean253. **Widgets** — Build reusable, const-optimized components; run `flutter test` after each feature26 - If tests fail: inspect widget tree with Flutter DevTools, fix failing assertions, re-run `flutter test`274. **Test** — Write widget and integration tests; confirm with `flutter test --coverage`28 - If coverage drops or tests fail: identify untested branches, add targeted tests, re-run before merging295. **Optimize** — Profile with Flutter DevTools (`flutter run --profile`), eliminate jank, reduce rebuilds30 - If jank persists: check rebuild counts in the Performance overlay, isolate expensive `build()` calls, apply `const` or move state closer to consumers3132## Reference Guide3334Load detailed guidance based on context:3536| Topic | Reference | Load When |37|-------|-----------|-----------|38| Riverpod | `references/riverpod-state.md` | State management, providers, notifiers |39| Bloc | `references/bloc-state.md` | Bloc, Cubit, event-driven state, complex business logic |40| GoRouter | `references/gorouter-navigation.md` | Navigation, routing, deep linking |41| Widgets | `references/widget-patterns.md` | Building UI components, const optimization |42| Structure | `references/project-structure.md` | Setting up project, architecture |43| Performance | `references/performance.md` | Optimization, profiling, jank fixes |4445## Code Examples4647### Riverpod Provider + ConsumerWidget (correct pattern)4849```dart50// provider definition51final counterProvider = StateNotifierProvider<CounterNotifier, int>(52 (ref) => CounterNotifier(),53);5455class CounterNotifier extends StateNotifier<int> {56 CounterNotifier() : super(0);57 void increment() => state = state + 1; // new instance, never mutate58}5960// consuming widget — use ConsumerWidget, not StatefulWidget61class CounterView extends ConsumerWidget {62 const CounterView({super.key});6364 @override65 Widget build(BuildContext context, WidgetRef ref) {66 final count = ref.watch(counterProvider);67 return Text('$count');68 }69}70```7172### Before / After — State Management7374```dart75// ❌ WRONG: app-wide state in setState76class _BadCounterState extends State<BadCounter> {77 int _count = 0;78 void _inc() => setState(() => _count++); // causes full subtree rebuild79}8081// ✅ CORRECT: scoped Riverpod consumer82class GoodCounter extends ConsumerWidget {83 const GoodCounter({super.key});84 @override85 Widget build(BuildContext context, WidgetRef ref) {86 final count = ref.watch(counterProvider);87 return IconButton(88 onPressed: () => ref.read(counterProvider.notifier).increment(),89 icon: const Icon(Icons.add), // const on static widgets90 );91 }92}93```9495## Constraints9697### MUST DO98- Use `const` constructors wherever possible99- Implement proper keys for lists100- Use `Consumer`/`ConsumerWidget` for state (not `StatefulWidget`)101- Follow Material/Cupertino design guidelines102- Profile with DevTools, fix jank103- Test widgets with `flutter_test`104105### MUST NOT DO106- Build widgets inside `build()` method107- Mutate state directly (always create new instances)108- Use `setState` for app-wide state109- Skip `const` on static widgets110- Ignore platform-specific behavior111- Block UI thread with heavy computation (use `compute()`)112113## Troubleshooting Common Failures114115| Symptom | Likely Cause | Recovery |116|---------|-------------|----------|117| `flutter analyze` errors | Unresolved imports, missing `const`, type mismatches | Fix flagged lines; run `flutter pub get` if imports are missing |118| Widget test assertion failures | Widget tree mismatch or async state not settled | Use `tester.pumpAndSettle()` after state changes; verify finder selectors |119| Build fails after adding package | Incompatible dependency version | Run `flutter pub upgrade --major-versions`; check pub.dev compatibility |120| Jank / dropped frames | Expensive `build()` calls, uncached widgets, heavy main-thread work | Use `RepaintBoundary`, move heavy work to `compute()`, add `const` |121| Hot reload not reflecting changes | State held in `StateNotifier` not reset | Use hot restart (`R` in terminal) to reset full app state |122123## Output Templates124125When implementing Flutter features, provide:1261. Widget code with proper `const` usage1272. Provider/Bloc definitions1283. Route configuration if needed1294. Test file structure