Skip to content

/flutter-dart-code-review

Library-agnostic Flutter/Dart code review checklist covering widget best practices, state management patterns (BLoC, Riverpod, Provider, GetX, MobX, Signals), Dart idioms, performance, accessibility, security, and clean architecture. Use when reviewing Flutter or Dart code,

From plugin
ecc
302k200 skills71 agents113 commands1 MCP

Claude Code

$ npx -y skills add affaan-m/ECC --skill flutter-dart-code-review --agent claude-code

SKILL.md

flutter-dart-code-review.SKILL.md
name: flutter-dart-code-review
description: Library-agnostic Flutter/Dart code review checklist covering widget best practices, state management patterns (BLoC, Riverpod, Provider, GetX, MobX, Signals), Dart idioms, performance, accessibility, security, and clean architecture. Use when reviewing Flutter or Dart code, whatever state management library the project uses.
metadata:
  origin: ECC

Flutter/Dart Code Review Best Practices

Comprehensive, library-agnostic checklist for reviewing Flutter/Dart applications. These principles apply regardless of which state management solution, routing library, or DI framework is used.

---

1. General Project Health

  • [ ] Project follows consistent folder structure (feature-first or layer-first)
  • [ ] Proper separation of concerns: UI, business logic, data layers
  • [ ] No business logic in widgets; widgets are purely presentational
  • [ ] `pubspec.yaml` is clean — no unused dependencies, versions pinned appropriately
  • [ ] `analysis_options.yaml` includes a strict lint set with strict analyzer settings enabled
  • [ ] No `print()` statements in production code — use `dart:developer` `log()` or a logging package
  • [ ] Generated files (`.g.dart`, `.freezed.dart`, `.gr.dart`) are up-to-date or in `.gitignore`
  • [ ] Platform-specific code isolated behind abstractions

---

2. Dart Language Pitfalls

  • [ ] **Implicit dynamic**: Missing type annotations leading to `dynamic` — enable `strict-casts`, `strict-inference`, `strict-raw-types`
  • [ ] **Null safety misuse**: Excessive `!` (bang operator) instead of proper null checks or Dart 3 pattern matching (`if (value case var v?)`)
  • [ ] **Type promotion failures**: Using `this.field` where local variable promotion would work
  • [ ] **Catching too broadly**: `catch (e)` without `on` clause; always specify exception types
  • [ ] **Catching `Error`**: `Error` subtypes indicate bugs and should not be caught
  • [ ] **Unused `async`**: Functions marked `async` that never `await` — unnecessary overhead
  • [ ] **`late` overuse**: `late` used where nullable or constructor initialization would be safer; defers errors to runtime
  • [ ] **String concatenation in loops**: Use `StringBuffer` instead of `+` for iterative string building
  • [ ] **Mutable state in `const` contexts**: Fields in `const` constructor classes should not be mutable
  • [ ] **Ignoring `Future` return values**: Use `await` or explicitly call `unawaited()` to signal intent
  • [ ] **`var` where `final` works**: Prefer `final` for locals and `const` for compile-time constants
  • [ ] **Relative imports**: Use `package:` imports for consistency
  • [ ] **Mutable collections exposed**: Public APIs should return unmodifiable views, not raw `List`/`Map`
  • [ ] **Missing Dart 3 pattern matching**: Prefer switch expressions and `if-case` over verbose `is` checks and manual casting
  • [ ] **Throwaway classes for multiple returns**: Use Dart 3 records `(String, int)` instead of single-use DTOs
  • [ ] **`print()` in production code**: Use `dart:developer` `log()` or the project's logging package; `print()` has no log levels and cannot be filtered

---

3. Widget Best Practices

Widget decomposition:

  • [ ] No single widget with a `build()` method exceeding ~80-100 lines
  • [ ] Widgets split by encapsulation AND by how they change (rebuild boundaries)
  • [ ] Private `_build*()` helper methods that return widgets are extracted to separate widget classes (enables element reuse, const propagation, and framework optimizations)
  • [ ] Stateless widgets preferred over Stateful where no mutable local state is needed
  • [ ] Extracted widgets are in separate files when reusable

Const usage:

  • [ ] `const` constructors used wherever possible — prevents unnecessary rebuilds
  • [ ] `const` literals for collections that don't change (`const []`, `const {}`)
  • [ ] Constructor is declared `const` when all fields are final

Key usage:

  • [ ] `ValueKey` used in lists/grids to preserve state across reorders
  • [ ] `GlobalKey` used sparingly — only when accessing state across the tree is truly needed
  • [ ] `UniqueKey` avoided in `build()` — it forces rebuild every frame
  • [ ] `ObjectKey` used when identity is based on a data object rather than a single value

Theming & design system:

  • [ ] Colors come from `Theme.of(context).colorScheme` — no hardcoded `Colors.red` or hex values
  • [ ] Text styles come from `Theme.of(context).textTheme` — no inline `TextStyle` with raw font sizes
  • [ ] Dark mode compatibility verified — no assumptions about light background
  • [ ] Spacing and sizing use consistent design tokens or constants, not magic numbers

Build method complexity:

  • [ ] No network calls, file I/O, or heavy computation in `build()`
  • [ ] No `Future.then()` or `async` work in `build()`
  • [ ] No subscription creation (`.listen()`) in `build()`
  • [ ] `setState()` localized to smallest possible subtree

---

4. State Management (Library-Agnostic)

These principles apply to all Flutter state management solutions (BLoC, Riverpod, Provider, GetX, MobX, Signals, ValueNotifier, etc.).

Architecture:

  • [ ] Business logic lives outside the widget layer — in a state management component (BLoC, Notifier, Controller, Store, ViewModel, etc.)
  • [ ] State managers receive dependencies via injection, not by constructing them internally
  • [ ] A service or repository layer abstracts data sources — widgets and state managers should not call APIs or databases directly
  • [ ] State managers have a single responsibility — no "god" managers handling unrelated concerns
  • [ ] Cross-component dependencies follow the solution's conventions:
  • In **Riverpod**: providers depending on providers via `ref.watch` is expected — flag only circular or overly tangled chains
  • In **BLoC**: blocs should not directly depend on other blocs — prefer shared repositories or presentation-layer coordination
  • In other solutions: follow the documented conventions for inter-component communication

###

Read more
@affaan-m
Ships withecc

Your agent can write code, but ECC gives it a coordinated engineering system and toolbox: it plans before it builds, verifies changes with tests, reviews its own work from a fresh context, remembers what matters, and turns repeated wins into reusable skills

302k200 skills71 agents1 MCP
Get the whole plugin, auto-invoked

Stars on GitHub

Momentum

stars in total
301.5k
Star history of affaan-m/ECC on GitHub, a chart by star-history.com

Other skills on ecc.

accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

@affaan-m@affaan-mInstall Skill
agent-architecture-audit
Auto-invoked

agent-architecture-aud…

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution,…

@affaan-m@affaan-mInstall Skill
agent-eval
Auto-invoked

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and…

@affaan-m@affaan-mInstall Skill
agent-harness-construction
Auto-invoked

agent-harness-construc…

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when…

@affaan-m@affaan-mInstall Skill
agent-introspection-debugging
Auto-invoked

agent-introspection-de…

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports.…

@affaan-m@affaan-mInstall Skill
agent-security-hardening
Auto-invoked

agent-security-hardeni…

Security hardening guidance for AI agent frameworks that process untrusted content, invoke tools, write workspace files, manage…

@affaan-m@affaan-mInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills12d309k
@mattpocock@mattpocockInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react3d252k
@facebook@facebookInstall Skill
act-on-feedback

act-on-feedback

Act on user feedback attached to the current session. Use when the user submits feedback on the session's changes via the Submit…

vscode3d195k
@microsoft@microsoftInstall Skill

Questions about flutter-dart-code-review.

Which coding agents can use flutter-dart-code-review?
flutter-dart-code-review installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.