From qe-framework
Builds cross-platform Flutter 3+ apps with Riverpod/Bloc state management, GoRouter navigation, custom widgets, and performance optimization.
How this skill is triggered — by the user, by Claude, or both
Slash command
/qe-framework:Qflutter-expertThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Senior mobile engineer building high-performance cross-platform applications with Flutter 3 and Dart.
Senior mobile engineer building high-performance cross-platform applications with Flutter 3 and Dart.
flutter pub get), configure routingflutter analyze
flutter analyze reports issues: fix all lints and warnings before proceeding; re-run until cleanflutter test after each feature
flutter testflutter test --coverage
flutter run --profile), eliminate jank, reduce rebuilds
build() calls, apply const or move state closer to consumersLoad 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 |
// 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');
}
}
// ❌ 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
);
}
}
/// A simple counter display widget.
///
/// Shows an integer value with formatted text.
///
/// Example:
/// ```dart
/// CounterDisplay(value: 42)
/// ```
class CounterDisplay extends StatelessWidget {
/// The count to display
final int value;
const CounterDisplay({super.key, required this.value});
@override
Widget build(BuildContext context) => Text('Count: $value');
}
/// Fetches user data with error handling.
/// Returns a Result<User> for safe error propagation.
Future<Result<User>> fetchUser(String id) async {
try {
final response = await http.get(Uri.parse('/api/users/$id'));
if (response.statusCode == 200) {
return Success(User.fromJson(jsonDecode(response.body)));
}
return Failure(Exception('HTTP ${response.statusCode}'));
} catch (e) {
return Failure(e as Exception);
}
}
/// Provides async user data with caching and error handling.
///
/// Usage:
/// ```dart
/// ref.watch(userProvider('123'))
/// ```
final userProvider = FutureProvider.family<User, String>((ref, id) async {
return fetchUser(id).then((result) => result.when(
success: (user) => user,
failure: (e) => throw e,
));
});
Widget Dartdoc:
/// Displays [title] with optional [subtitle].
///
/// Renders a Material-style card with elevation [elevation].
///
/// Example:
/// ```dart
/// MyCard(title: 'Hello', elevation: 4)
/// ```
Function Dartdoc:
/// Builds a greeting message from [firstName] and [lastName].
///
/// Throws [ArgumentError] if either param is empty.
/// Returns formatted String like "John Doe".
String greetUser(String firstName, String lastName) => '$firstName $lastName';
Class Dartdoc:
/// State notifier for managing counter logic.
///
/// ```dart
/// final c = CounterNotifier();
/// c.increment(); // state = 1
/// ```
class CounterNotifier extends StateNotifier<int> { ... }
Commands:
dart analyze — check all lints, run before commitdart fix --apply — auto-fix fixable issuesdart format — format code to style guideflutter analyze — Flutter-specific lintsConfig (analysis_options.yaml):
include: package:flutter_lints/flutter.yaml
linter:
rules:
- avoid_empty_else
- constant_identifier_names
- prefer_const_constructors
- prefer_const_declarations
- avoid_print
flutter_secure_storage for tokens, passwords, sensitive datadio + custom HttpClient)flutter build apk --obfuscate --split-debug-infoconst constructors, scoped providers (reduces jank)dispose() TextEditingController (prevents memory leaks)AppLocalizations for i18n (centralizes localization)const constructors wherever possibleConsumer/ConsumerWidget for state (not StatefulWidget)flutter_testbuild() methodsetState for app-wide stateconst on static widgetscompute())| 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 |
Provide widget code with const usage, provider/Bloc definitions, route config if needed, and test structure.
npx claudepluginhub inho-team/qe-framework --plugin qe-frameworkCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.