flutter-dart-code-review
Helps your agent thoroughly review Flutter and Dart code. It checks best practices, state management, performance, and security, without focusing on specific libraries.
What it does
This is a guide for reviewing Flutter and Dart code. It checks if the code is well-organized, uses good programming practices, and avoids common errors, regardless of the state management library used.
When to use it
- ✓When reviewing someone else's code.
- ✓Before finalizing a feature.
- ✓To learn best practices in Flutter/Dart.
Example of what to ask your AI
“Review this Flutter code, focusing on best practices for organization and potential errors.”
Want more? Open the sections below.
How to use
The easiest way: copy the message below and paste it into Claude, ChatGPT, Cursor or any AI. It reads the skill and follows the instructions.
Skill link
Ready-to-paste message
How it works
The guide checks the project structure, correct use of the Dart language, best practices for creating widgets (visual screen parts), and how state (changing data) is managed. It ensures the code is efficient, accessible, and secure.
Installation
Easiest way: copy the skill link and paste it into Claude, ChatGPT or Cursor asking it to follow the instructions.
In the terminal (Claude Code, Codex, Cursor), in your project folder:
npx skills add affaan-m/ECC --skill flutter-dart-code-reviewOr download just the file:
curl -L https://raw.githubusercontent.com/affaan-m/ECC/main/pi/core/skills/flutter-dart-code-review/SKILL.md -o SKILL.mdTechnical content (original SKILL.md)
Original text by the author, straight from GitHub.
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.yamlis clean — no unused dependencies, versions pinned appropriately -
analysis_options.yamlincludes a strict lint set with strict analyzer settings enabled - No
print()statements in production code — usedart:developerlog()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— enablestrict-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.fieldwhere local variable promotion would work - Catching too broadly:
catch (e)withoutonclause; always specify exception types - Catching
Error:Errorsubtypes indicate bugs and should not be caught - Unused
async: Functions markedasyncthat neverawait— unnecessary overhead -
lateoveruse:lateused where nullable or constructor initialization would be safer; defers errors to runtime - String concatenation in loops: Use
StringBufferinstead of+for iterative string building - Mutable state in
constcontexts: Fields inconstconstructor classes should not be mutable - Ignoring
Futurereturn values: Useawaitor explicitly callunawaited()to signal intent -
varwherefinalworks: Preferfinalfor locals andconstfor 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-caseover verboseischecks and manual casting - Throwaway classes for multiple returns: Use Dart 3 records
(String, int)instead of single-use DTOs -
print()in production code: Usedart:developerlog()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:
-
constconstructors used wherever possible — prevents unnecessary rebuilds -
constliterals for collections that don't change (const [],const {}) - Constructor is declared
constwhen all fields are final
Key usage:
-
ValueKeyused in lists/grids to preserve state across reorders -
GlobalKeyused sparingly — only when accessing state across the tree is truly needed -
UniqueKeyavoided inbuild()— it forces rebuild every frame -
ObjectKeyused when identity is based on a data object rather than a single value
Theming & design system:
- Colors come from
Theme.of(context).colorScheme— no hardcodedColors.redor hex values - Text styles come from
Theme.of(context).textTheme— no inlineTextStylewith 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()orasyncwork inbuild() - No subscription creation (
.listen()) inbuild()
…
FAQ
What does 'library-agnostic' mean?
It means the tips work for any state management library (like BLoC, Riverpod, Provider, etc.) you are using in your Flutter project.
Why not use `print()` in the final code?
`print()` can clutter the app's log and doesn't have severity levels, making it hard to identify important messages. It's better to use specific logging tools.
What are 'widgets'?
Widgets are the building blocks of user interfaces in Flutter. They represent visual elements like text, buttons, layouts, etc.
Details
Original description by the author
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.
repo: affaan-m/ECC
Popularity
- GitHub stars
- 280k
- Ranking position
- #55
- License
- MIT
- Updated
- 10/15/2026
Comments
- …
More skills from this repository
accessibility
Helps your agent create interfaces that everyone can use. Ensures websites and apps work well for people with disabilities, like those who are blind or have reduced mobility.
affaan-m/ECC
agent-architecture-audit
Makes your agent check if everything is working correctly. It finds and fixes problems in AI systems, ensuring they perform as expected.
affaan-m/ECC
agent-eval
Helps your agent compare different AI coding tools. It measures which one is faster, cheaper, and more reliable for specific tasks.
affaan-m/ECC
agent-harness-construction
Makes your agent better understand how to perform tasks. It optimizes the tools and instructions the agent uses to increase its chances of success.
affaan-m/ECC
Similar skills
flutter-animating-apps
Lets your agent add animated effects and transitions in Flutter apps. It's useful for creating motion and visual design in iOS and Android apps.
nexu-io/open-design
add-app-clip
Lets your agent add an iOS App Clip to an Expo app. It's useful for creating lightweight app versions opened by links.
sickn33/agentic-awesome-skills
android-dev
Helps develop Android applications. It covers different ways to create apps, native or cross-platform.
sickn33/agentic-awesome-skills