accessibility
Use when working on accessibility, a11y, WCAG, ARIA, screen readers, keyboard nav, focus order, contrast, alt text, captions,…
Use when setting up ChangeNotifier models, providing them to the widget tree, consuming state with Consumer or Provider.of, or optimizing rebuilds.
Claude Code
$ npx -y skills add evanca/flutter-ai-rules --skill flutter-change-notifier --agent claude-code
Codex
$ npx skills add evanca/flutter-ai-rules --skill flutter-change-notifier -a codex -y
Cursor
$ npx skills add evanca/flutter-ai-rules --skill flutter-change-notifier -a cursor -y
Gemini CLI
$ npx skills add evanca/flutter-ai-rules --skill flutter-change-notifier -a gemini-cli -y
GitHub Copilot
$ npx skills add evanca/flutter-ai-rules --skill flutter-change-notifier -a github-copilot -y
OpenCode
$ npx skills add evanca/flutter-ai-rules --skill flutter-change-notifier -a opencode -y
Windsurf
$ npx skills add evanca/flutter-ai-rules --skill flutter-change-notifier -a windsurf -y
name: flutter-change-notifier description: "Use when setting up ChangeNotifier models, providing them to the widget tree, consuming state with Consumer or Provider.of, or optimizing rebuilds." license: MIT
This skill defines how to correctly use `ChangeNotifier` with the `provider` package for state management in Flutter.
---
Extend `ChangeNotifier` to manage state. Keep internal state **private** and expose **unmodifiable views**. Call `notifyListeners()` on every state change.
class CartModel extends ChangeNotifier {
final List<Item> _items = [];
UnmodifiableListView<Item> get items => UnmodifiableListView(_items);
void add(Item item) {
_items.add(item);
notifyListeners();
}
void removeAll() {
_items.clear();
notifyListeners();
}
}---
ChangeNotifierProvider( create: (context) => CartModel(), child: MyApp(), )
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CartModel()),
ChangeNotifierProvider(create: (_) => UserModel()),
],
child: MyApp(),
)---
Consumer<CartModel>(
builder: (context, cart, child) => Stack(
children: [
if (child != null) child,
Text('Total price: ${cart.totalPrice}'),
],
),
child: const SomeExpensiveWidget(), // rebuilt only once
)HumongousWidget(
child: AnotherMonstrousWidget(
child: Consumer<CartModel>(
builder: (context, cart, child) {
return Text('Total price: ${cart.totalPrice}');
},
),
),
)Use `Provider.of<T>(context, listen: false)` when you only need to **call methods** on the model, not react to state changes:
Provider.of<CartModel>(context, listen: false).removeAll();
---
---
Write **unit tests** for your `ChangeNotifier` models to verify state changes and notifications:
test('adding item updates total', () {
final cart = CartModel();
var notified = false;
cart.addListener(() => notified = true);
cart.add(Item('Book'));
expect(cart.items.length, 1);
expect(notified, isTrue);
});---
36 Flutter and Dart skills your coding agent loads by itself, sourced only from official documentation. A skill is a folder with a SKILL.md file.
Use when working on accessibility, a11y, WCAG, ARIA, screen readers, keyboard nav, focus order, contrast, alt text, captions,…
Use when creating a feature, designing folder structure, adding repositories/services/view models, wiring dependency injection,…
Use when creating a Cubit or Bloc, modeling state with sealed classes or status enums, wiring…
Use when asked to review a PR, MR, branch, or diff, audit changed files, or check code quality.
Use when writing switch statements, refactoring if-else chains, creating data classes, choosing records vs classes, destructuring…
Use when building AI agents in Dart, implementing Genkit flows or tools, integrating LLMs into Dart or Flutter applications, or…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.