# Flutter

> Operational skill for Flutter: widgets, state management choices, async UI, platform channels awareness, and release build hygiene.

- Skill: `alivirgo/flutter` (Agent Skill)
- Install (CLI): `npx skillmds@latest add alivirgo/flutter`
- Raw SKILL.md: https://api.skillmd.com/api/skills/alivirgo/flutter/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: alivirgo (https://skillmd.com/u/alivirgo)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/alivirgo/flutter

---


# Flutter Cross-Platform UI AI Skill Guide

## Overview & Engine Architecture

Flutter paints UI with a widget tree compiled to native ARM/x64 (and web/desktop targets). Everything is a widget; rebuilds are cheap when state is localized. Agents prefer composition over deep inheritance, choose an explicit state approach (Riverpod/Bloc/Provider) and stick to it, and keep platform-specific code behind clean facades.

```
Dart app
  -> Widget tree (build)
      -> Element / RenderObject
          -> Skia / Impeller
              -> iOS / Android / Web / Desktop
```

## When to use this skill

- Building or refactoring Flutter screens
- Fixing unnecessary rebuilds and async UI races
- Adding platform views or method channels carefully
- Preparing release/signing build configs

## Operational directives

1. Keep `build()` pure - no side effects; trigger work from callbacks/initState/providers.
2. Use `const` constructors where possible to cut rebuild cost.
3. Handle loading/error/empty states explicitly for every async boundary.
4. Do not block the UI isolate with heavy JSON/parse - use compute/isolates when needed.
5. Match Flutter/Dart SDK constraints in CI to local `pubspec` constraints.

## Widget sketch

```dart
class ItemCount extends StatelessWidget {
  const ItemCount({super.key, required this.qty});
  final int qty;

  @override
  Widget build(BuildContext context) {
    return Text('Qty: $qty');
  }
}

class AddItemButton extends StatefulWidget {
  const AddItemButton({super.key, required this.onAdd});
  final Future<void> Function() onAdd;

  @override
  State<AddItemButton> createState() => _AddItemButtonState();
}

class _AddItemButtonState extends State<AddItemButton> {
  bool _busy = false;

  Future<void> _handle() async {
    if (_busy) return;
    setState(() => _busy = true);
    try {
      await widget.onAdd();
    } finally {
      if (mounted) setState(() => _busy = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: _busy ? null : _handle,
      child: Text(_busy ? 'Saving...' : 'Add'),
    );
  }
}
```

## Commands

```bash
flutter doctor
flutter pub get
flutter run
flutter test
flutter build apk
flutter build ipa
```

## Common pitfalls

| Pitfall | Why it hurts | Fix |
| --- | --- | --- |
| setState after dispose | Crashes | Check `mounted` |
| Giant Build methods | Unmaintainable rebuilds | Extract widgets |
| Ignoring null-safety | Runtime surprises | Sound null safety |
| Unsigned release experiments | Store rejection | Proper signing configs |

## Best practices

- Use keys when reordering lists of stateful children.
- Centralize theme and text styles; avoid one-off magic numbers.
- Add golden/widget tests for critical UI; integration tests for flows.
- Document min iOS/Android OS versions for the project.

## Limitations

- Plugin quality varies across platforms - verify each target.
- Impeller vs Skia behavior can differ by Flutter version/OS.
- Heavy native UI embedding is still a specialized path.

## Related skills

- `@dart` - language fundamentals when present
- `@android-studio` / `@xcode-ios` - native tooling underneath
- `@firebase` - common backend for Flutter apps

