This skill provides patterns and templates for Flutter 3.38 / Dart 3.11 cross-platform mobile development. It should be activated when building Flutter screens, Riverpod providers, Freezed models, or widget tests.
NO FLUTTER UI WITHOUT RUNNING THE MFRI RISK SCORE FIRST — load reference/mfri-scoring.md before writing any screen
lib/features/<feature>/data/, domain/, presentation/ layers (clean architecture)freezed for immutable modelsfirebase_core, cloud_firestore, firebase_authflutter create --org com.company --platforms ios,android my_app
cd my_app
# Add core dependencies
flutter pub add flutter_riverpod riverpod_annotation
flutter pub add freezed_annotation json_annotation go_router firebase_core cloud_firestore firebase_auth
flutter pub add dio
flutter pub add dev:riverpod_generator dev:freezed dev:json_serializable dev:build_runner dev:mocktail
# Run code generation
dart run build_runner build --delete-conflicting-outputs
In a Melos monorepo, use these commands at the workspace root:
melos bootstrap — installs all Flutter workspace dependencies (run at root, NOT flutter pub get)melos run test — runs tests across all packagesmelos run build_runner — runs code generation across all packagesIn a Melos workspace, individual apps reference shared packages by path rather than publishing them. Example:
dependencies:
<shared_ui_package>:
path: ../../packages/<shared_ui_package>
<shared_core_package>:
path: ../../packages/<shared_core_package>
Do NOT create a lib/design_system/ directory in individual apps — shared UI components belong in the workspace's shared UI package.
In a Melos workspace, place the shared Dio instance with auth + retry interceptors in the shared core package's providers directory. Do NOT create new Dio instances in individual features.
Before creating or modifying any widget, screen, or visual component:
reference/mfri-scoring.md and complete the checkpoint template. Score < 3 = stop and redesign. Score 3-5 = add a validation milestone.ui-standards-tokens skill — read reference/ui-design-tokens.md for spacing, color, typography, radius tokensAppSpacing.md), color approach (Theme.of(context).colorScheme), and typography pattern (Theme.of(context).textTheme) you will use?reference/ui-accessibility-patterns.md before adding interactive elementsreference/flutter-templates.md for all code templates (Freezed models, Riverpod providers, screens, GoRouter, tests, Firebase integration)lib/features/<feature>/data/, domain/, presentation/ directoriesdata/models/ with Firestore serialization@riverpod annotation in presentation/providers/ConsumerWidget screens that watch AsyncValue<T> providersdart run build_runner build --delete-conflicting-outputsProviderScope overrides| Pattern | Description |
|---------|-------------|
| @freezed models | Immutable data classes with fromFirestore factory |
| @riverpod providers | Code-generated state notifiers with AsyncValue |
| ConsumerWidget | Widgets that watch providers via ref.watch() |
| AsyncValue.when() | Handle loading/error/data states declaratively |
| Clean Architecture | Separate data/domain/presentation layers |
| GoRouter | Declarative routing with path parameters |
| Firebase Auth | Stream-based auth state with authStateChanges() |
| Firestore snapshots | Real-time data with .snapshots() streams |
For architecture patterns, accessibility, performance, UX, and premium polish guidelines:
Read reference/flutter-architecture-patterns.md — Sealed classes, Result types, Riverpod AsyncNotifier
Read reference/flutter-performance-ux.md — Accessibility, performance, haptic feedback, shimmer, animations
Read reference/flutter-design-polish.md — Glassmorphism, premium cards, dark/light themes, gradients
Read reference/accessibility-audit-checklist.md — WCAG 2.1 audit checklist (used by accessibility-auditor agent)
Read reference/flutter-security-hardening.md — Security hardening & privacy compliance (used by flutter-security-expert agent)
Read reference/smart-dumb-widgets.md — Smart (ConsumerWidget) vs Dumb (StatelessWidget) pattern, ref.watch/read placement rules, decision tree, Riverpod enforcement gates
Read reference/flutter-use-case-layer.md — When to add a use case, when not to, file location, example with two repositories, unit testing with fakes
Before generating code, consult these sources for current syntax and APIs:
| Source | URL / Tool | Purpose |
|--------|-----------|---------|
| Flutter / Dart | Dart MCP server | Latest Flutter widgets, Dart syntax, platform APIs |
| Riverpod | Context7 MCP | Provider types, ref usage, AsyncValue patterns |
| Firebase Firestore | Firebase MCP server | Firestore operations, rules validation, auth flows |
For iOS-specific workflows, use the xcodebuild MCP server instead of raw CLI commands. It provides structured output, error parsing, and debugging that flutter build ios via Bash cannot.
| Task | Use This | Not This |
|------|----------|----------|
| Build iOS for simulator | build_sim (MCP) | flutter build ios --simulator (Bash) |
| Build + install + launch on simulator | build_run_sim (MCP) | flutter run (Bash) |
| Build for physical device | build_device (MCP) | flutter build ios (Bash) |
| Debug a crash or inspect state | debug_attach_sim → debug_variables (MCP) | Manual Xcode debugging |
| Capture runtime logs | start_sim_log_cap / stop_sim_log_cap (MCP) | Reading console manually |
| Check signing/scheme config | show_build_settings / list_schemes (MCP) | xcodebuild -showBuildSettings (Bash) |
| UI interaction (tap, swipe, type) | tap, swipe, type_text (MCP) | Not available via Bash |
| Build Android | flutter build apk (Bash) | N/A — XcodeBuildMCP is iOS/macOS only |
1. discover_projs → find ios/Runner.xcworkspace
2. list_schemes → identify the Runner scheme
3. build_run_sim → build, install, and launch on simulator
4. start_sim_log_cap → begin capturing logs
5. [reproduce the issue]
6. debug_attach_sim → attach LLDB debugger
7. debug_breakpoint_add → set breakpoint at suspect line
8. debug_variables / debug_stack → inspect state
9. stop_sim_log_cap → get captured logs
ios/Runner.xcworkspace, not the project rootflutter build ios once first to generate the Xcode project and Podsshow_build_settings exposes signing config — use this to diagnose code signing failuresRunner scheme by defaultFor cross-platform E2E testing, use the maestro MCP server. It runs test flows on both iOS simulator and Android emulator from natural language prompts.
| Test Type | Tool | When |
|-----------|------|------|
| Widget/unit tests | flutter test (Bash) or dart-mcp-server run_tests | Every feature — fast, isolated, no device needed |
| iOS build + quick visual check | xcodebuild MCP (build_run_sim, screenshot) | Spot-checking a screen during development |
| Repeatable E2E flows | maestro MCP | Login, checkout, CRUD journeys — saved and rerunnable |
| Cross-platform E2E | maestro MCP | Same YAML flow runs on iOS simulator AND Android emulator |
| CI/CD regression suite | maestro test test/e2e/ (Bash) | Pre-merge gate in GitHub Actions |
1. Build and launch app (XcodeBuildMCP for iOS, flutter run for Android)
2. Describe the test flow in natural language
3. Claude generates YAML via Maestro MCP and runs it
4. Claude reports pass/fail per step
5. Save generated YAML to test/e2e/<flow-name>.yaml for reuse
test/e2e/ at the project rootlogin-flow.yaml, create-workout-flow.yamlappId matching your app's bundle IDSemantics widgets have labelswaitForAnimationToEnd or extendedWaitUntil for slow transitions, not hardcoded sleepsid attributes for reliable cross-platform selectorsflutter run # Run on connected device/emulator
flutter test # Run tests
flutter build apk # Build Android APK
flutter build ios # Build iOS (also generates Xcode project)
flutter pub get # Install dependencies
flutter clean # Clean build artifacts
dart run build_runner build --delete-conflicting-outputs # Run code generation
flutter analyze # Static analysis
Build runner fails: Delete .dart_tool/build/, run flutter clean, retry codegen
Missing generated files: Ensure part directives match filename (e.g., part 'user_model.g.dart';)
Provider not found: Run dart run build_runner build, import generated .g.dart file
Firestore Timestamp errors: Use (data['createdAt'] as Timestamp).toDate() in fromFirestore
Hot reload breaks state: Restart app fully when changing provider signatures
AsyncValue stuck loading: Check repository returns data, use AsyncValue.guard() to catch errors
Navigator.push with raw strings — use GoRouter type-safe routes exclusivelyAsyncValue.error, never null/empty fallbacksColor(0x...) or Colors.* — use Theme.of(context).colorScheme.*EdgeInsets with numeric values — use AppSpacing.* tokensTextStyle(fontSize: ...) — use Theme.of(context).textTheme.*Anti-pattern — boolean flags that create invalid states:
// ❌ 4 booleans = 16 possible states, most invalid
class LoadState {
bool isLoading = false;
bool isError = false;
bool isEmpty = false;
bool isSuccess = false;
// isLoading=true AND isSuccess=true is invalid but representable
}
Correct — sealed class makes invalid states unrepresentable:
// ✅ Dart 3 sealed class — exactly 4 valid states
sealed class LoadState<T> {}
final class LoadingState<T> extends LoadState<T> {}
final class ErrorState<T> extends LoadState<T> {
final Object error;
final StackTrace? stack;
ErrorState(this.error, [this.stack]);
}
final class EmptyState<T> extends LoadState<T> {}
final class SuccessState<T> extends LoadState<T> {
final T data;
SuccessState(this.data);
}
// Usage — exhaustive pattern matching (compiler enforces all cases):
Widget build(BuildContext context) {
return switch (state) {
LoadingState() => const CircularProgressIndicator(),
ErrorState(:final error) => ErrorWidget(error.toString()),
EmptyState() => const Text('No items'),
SuccessState(:final data) => ItemList(data),
};
}
Rule: Use sealed classes + switch expressions for any state with 3+ mutually exclusive cases. Applies to: UI state, network state, auth state, form state.
Applies to: Flutter 3.41.x / Dart 3.10.9+ (sealed classes require Dart 3.0+)
Library-agnostic comparison (for Riverpod-specific patterns, see .claude/skills/riverpod-patterns/):
| Library | Best for | Avoid when | |---------|----------|-----------| | Riverpod | Complex apps, DI, testability | Simple apps — overhead not justified | | Bloc | Team environments, strict separation, audit-ready | Solo devs — too much boilerplate | | Provider | Simple state, migration path from InheritedWidget | New projects — use Riverpod instead | | GetX | Rapid prototyping | Production apps — couples UI to logic | | flutter_hooks | Functional widget style, reusable stateful logic | Mixed teams unfamiliar with hooks | | setState | Local ephemeral UI state (single widget) | Shared state across widgets | | InheritedWidget | Framework/library authors only | App code — use Provider/Riverpod |
This workspace's stack uses Riverpod — see .claude/skills/riverpod-patterns/ for detailed patterns.
After writing Dart code, dispatch these reviewer agents:
riverpod-reviewer — state management, provider types, AsyncValue handlingflutter-security-expert — secure storage, certificate pinning, data protectionaccessibility-auditor — WCAG 2.1 compliance, Semantics widgets, touch targetsPre-submit checks (smart/dumb pattern):
shared_ui/ widgets extend StatelessWidget — zero ref/ConsumerWidget usageref.watch() only in ConsumerWidget build(); ref.read() only in callbacksFor all code templates (pubspec.yaml, Freezed models, Riverpod providers, screen widgets, GoRouter config, widget tests, Firebase integration, repository patterns):
Read reference/flutter-templates.md
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer