$npx -y skills add Jeffallan/claude-skills --skill flutter-expertUse 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.
| 1 | # Flutter Expert |
| 2 | |
| 3 | Senior mobile engineer building high-performance cross-platform applications with Flutter 3 and Dart. |
| 4 | |
| 5 | ## When to Use This Skill |
| 6 | |
| 7 | - Building cross-platform Flutter applications |
| 8 | - Implementing state management (Riverpod, Bloc) |
| 9 | - Setting up navigation with GoRouter |
| 10 | - Creating custom widgets and animations |
| 11 | - Optimizing Flutter performance |
| 12 | - Platform-specific implementations |
| 13 | |
| 14 | ## Core Workflow |
| 15 | |
| 16 | 1. **Setup** — Scaffold project, add dependencies (`flutter pub get`), configure routing |
| 17 | 2. **State** — Define Riverpod providers or Bloc/Cubit classes; verify with `flutter analyze` |
| 18 | - If `flutter analyze` reports issues: fix all lints and warnings before proceeding; re-run until clean |
| 19 | 3. **Widgets** — Build reusable, const-optimized components; run `flutter test` after each feature |
| 20 | - If tests fail: inspect widget tree with Flutter DevTools, fix failing assertions, re-run `flutter test` |
| 21 | 4. **Test** — Write widget and integration tests; confirm with `flutter test --coverage` |
| 22 | - If coverage drops or tests fail: identify untested branches, add targeted tests, re-run before merging |
| 23 | 5. **Optimize** — Profile with Flutter DevTools (`flutter run --profile`), eliminate jank, reduce rebuilds |
| 24 | - If jank persists: check rebuild counts in the Performance overlay, isolate expensive `build()` calls, apply `const` or move state closer to consumers |
| 25 | |
| 26 | ## Reference Guide |
| 27 | |
| 28 | Load detailed guidance based on context: |
| 29 | |
| 30 | | Topic | Reference | Load When | |
| 31 | |-------|-----------|-----------| |
| 32 | | Riverpod | `references/riverpod-state.md` | State management, providers, notifiers | |
| 33 | | Bloc | `references/bloc-state.md` | Bloc, Cubit, event-driven state, complex business logic | |
| 34 | | GoRouter | `references/gorouter-navigation.md` | Navigation, routing, deep linking | |
| 35 | | Widgets | `references/widget-patterns.md` | Building UI components, const optimization | |
| 36 | | Structure | `references/project-structure.md` | Setting up project, architecture | |
| 37 | | Performance | `references/performance.md` | Optimization, profiling, jank fixes | |
| 38 | |
| 39 | ## Code Examples |
| 40 | |
| 41 | ### Riverpod Provider + ConsumerWidget (correct pattern) |
| 42 | |
| 43 | ```dart |
| 44 | // provider definition |
| 45 | final counterProvider = StateNotifierProvider<CounterNotifier, int>( |
| 46 | (ref) => CounterNotifier(), |
| 47 | ); |
| 48 | |
| 49 | class CounterNotifier extends StateNotifier<int> { |
| 50 | CounterNotifier() : super(0); |
| 51 | void increment() => state = state + 1; // new instance, never mutate |
| 52 | } |
| 53 | |
| 54 | // consuming widget — use ConsumerWidget, not StatefulWidget |
| 55 | class CounterView extends ConsumerWidget { |
| 56 | const CounterView({super.key}); |
| 57 | |
| 58 | @override |
| 59 | Widget build(BuildContext context, WidgetRef ref) { |
| 60 | final count = ref.watch(counterProvider); |
| 61 | return Text('$count'); |
| 62 | } |
| 63 | } |
| 64 | ``` |
| 65 | |
| 66 | ### Before / After — State Management |
| 67 | |
| 68 | ```dart |
| 69 | // ❌ WRONG: app-wide state in setState |
| 70 | class _BadCounterState extends State<BadCounter> { |
| 71 | int _count = 0; |
| 72 | void _inc() => setState(() => _count++); // causes full subtree rebuild |
| 73 | } |
| 74 | |
| 75 | // ✅ CORRECT: scoped Riverpod consumer |
| 76 | class GoodCounter extends ConsumerWidget { |
| 77 | const GoodCounter({super.key}); |
| 78 | @override |
| 79 | Widget build(BuildContext context, WidgetRef ref) { |
| 80 | final count = ref.watch(counterProvider); |
| 81 | return IconButton( |
| 82 | onPressed: () => ref.read(counterProvider.notifier).increment(), |
| 83 | icon: const Icon(Icons.add), // const on static widgets |
| 84 | ); |
| 85 | } |
| 86 | } |
| 87 | ``` |
| 88 | |
| 89 | ## Constraints |
| 90 | |
| 91 | ### MUST DO |
| 92 | - Use `const` constructors wherever possible |
| 93 | - Implement proper keys for lists |
| 94 | - Use `Consumer`/`ConsumerWidget` for state (not `StatefulWidget`) |
| 95 | - Follow Material/Cupertino design guidelines |
| 96 | - Profile with DevTools, fix jank |
| 97 | - Test widgets with `flutter_test` |
| 98 | |
| 99 | ### MUST NOT DO |
| 100 | - Build widgets inside `build()` method |
| 101 | - Mutate state directly (always create new instances) |
| 102 | - Use `setState` for app-wide state |
| 103 | - Skip `const` on static widgets |
| 104 | - Ignore platform-specific behavior |
| 105 | - Block UI thread with heavy computation (use `compute()`) |
| 106 | |
| 107 | ## Troubleshooting Common Failures |
| 108 | |
| 109 | | Symptom | Likely Cause | Recovery | |
| 110 | |---------|-------------|----------| |
| 111 | | `flutter analyze` errors | Unresolved imports, missing `const`, type mismatches | Fix flagged lines; run `flutter pub get` if imports are missing | |
| 112 | | Widget test assertion failures | Widget tree mismatch or async state not settled | Use `tester.pumpAndSettle()` after state changes; verify finder selectors | |
| 113 | | Build fails after adding package | Incompatible dependency version | Run `flutter pub upgrade --major-versions`; check |