Cursor Rules for Flutter: Widgets, State, and Tests
A practical rule set for Flutter projects in Cursor, covering widget structure, state management, platform boundaries, and verification commands. Adapt each template to your project and keep shared product context and technical decisions in fenbs.
Updated 6 min read
Cursor rules for a Flutter project tell the assistant how your widget tree is organized, which state management approach the project uses, how platform-specific code is handled, and which commands to run when verifying changes. Flutter projects vary widely: some use Provider, some use Riverpod, some use Bloc, and some use plain setState. An assistant that does not know which approach your project uses may introduce a different pattern with every new widget it generates. fenbs helps teams keep the product context and technical decisions that make their Flutter rules specific — so every connected assistant starts a session knowing how the project actually works, not just how Flutter works in general.
The templates below are starting points. Replace package names, folder paths, and test details with your actual project values. Test each rule on a real file before committing it, and remove any rule that conflicts with your existing code.
Widget structure and organization
The most common structural question in Flutter is where a new widget should go: in a screens folder, a features folder, or a shared components folder. A rule that names your folder structure and the distinction between screen widgets and reusable components prevents the assistant from creating files in the wrong location.
Widget organization: - lib/features/: feature-specific widgets, organized by feature name Each feature folder contains: widgets/, models/, and its own providers or cubits - lib/shared/widgets/: reusable UI components used across features - lib/shared/theme/: colors, text styles, spacing constants Screen widgets are stateless where possible. Extract reusable parts to lib/shared/widgets/ when used in more than one feature. Do not put business logic in widget build() methods.
State management rules
Flutter's state management options are one of the most common sources of inconsistency. When the assistant encounters a widget without a rule, it may use setState, a Provider, a Riverpod notifier, or a Bloc depending on what it has seen most recently. A rule that names your chosen approach prevents a mixture of patterns that is hard to maintain.
State management: Riverpod - Use @riverpod generated providers (using riverpod_generator) - Providers live in the same folder as the feature they serve - Do not use setState in widgets that have business logic (setState is acceptable for UI-only state like animation toggles) - Do not introduce Provider, Bloc, or GetX - Use ref.watch() for reactive state; ref.read() only for actions - Async providers: use AsyncNotifier or FutureProvider; do not manually handle loading/error in widgets
Platform and platform channel rules
Flutter apps run on multiple platforms, and platform-specific code needs to be isolated properly. An assistant that adds platform-specific behavior in the middle of a shared widget creates code that will fail to build on other platforms. A rule about how platform code is handled in your project prevents this.
Platform code: - Supported platforms: iOS and Android (primary), web (secondary) - Platform-specific implementations go in lib/platform/ with a shared interface Use conditional imports or a factory pattern, not if (Platform.isIOS) in widgets - Do not add new native plugins without team approval - Approved plugins are listed in pubspec.yaml — do not add new dependencies without checking there first - For platform channels, add a method channel wrapper in lib/platform/channels/
Navigation rules
Flutter has several navigation approaches: the original Navigator API, Navigator 2.0, GoRouter, AutoRoute, and others. A project that uses GoRouter has different conventions for named routes, parameters, and deep links than one using the imperative Navigator. A short navigation rule prevents the assistant from mixing approaches.
Navigation: GoRouter - Routes are defined in lib/router/router.dart - Use context.go() for navigation; do not use Navigator.push() for new code - Named routes are defined as constants in lib/router/routes.dart - Deep links are configured in router.dart — add a new route there before adding a new screen - Do not pass large objects through route params; use a state provider instead
Testing and verification rules
Flutter testing covers widget tests, unit tests, and integration tests, each with different setup requirements. A rule that names your test setup and the commands to run keeps new tests consistent with existing ones and prevents the assistant from writing tests using the wrong helper classes or runner.
Tests: - Widget tests: test/ directory, file naming *_test.dart - Use flutter_test for widget tests; mocktail for mocking - Provider overrides in tests: use ProviderScope with overrides Commands: - Run all tests: flutter test - Run with coverage: flutter test --coverage - Analyze: flutter analyze - Format: dart format . Run flutter analyze before saying a change is complete.
Keep Flutter rules with the product context behind them
Add your approved Flutter rules to fenbs Skills and prompts alongside the product context that makes them specific: which platforms are primary, which state management approach was chosen and why, which plugins are approved. When the project upgrades Flutter or adopts a new package, update fenbs once and every connected assistant starts the next session from the current setup, without discovering outdated instructions in a local file.
Create a free accountFree for one person · No credit card · Works with Claude, ChatGPT, Cursor and more
How to do this with fenbs
- Create a free account and add a project for your Flutter app.
- Add a skill or prompt for each rule area: widget structure, state management, platform handling, navigation, and tests. Keep each focused on your actual project conventions, not Flutter defaults.
- Record the key decisions in Decisions and rules: which state management approach was chosen and why, which platforms are the priority targets, which third-party packages are approved. These give the assistant context the rule file alone cannot provide.
- When the team upgrades Flutter or adopts a new package, update the relevant rules in fenbs and record the change as a lesson if the old approach caused problems.
- Connect your AI tools from Integrations so they read the current rules and product context before starting work on the app.
What rules cannot cover in a Flutter project
Rules handle coding conventions. They do not cover product requirements: which screens need to work offline, what the accessibility requirements are, or why a particular feature uses a specific data model. That context belongs in your project and task notes in fenbs. When the assistant needs to understand a product decision to implement a widget correctly, the answer is in the project notes, not in a coding rule.
fenbs does not run Flutter commands or interact with the device. After the assistant makes changes, run flutter analyze and flutter test yourself to verify the result. The cursor rules for AI projects article has more on combining coding rules with project-level context for mobile apps.
Flutter rule files benefit from a brief note about the Dart SDK version alongside the Flutter version. Some Dart features — pattern matching, records, sealed classes — are version-specific. A rule that references syntax from a recent Dart release without noting the required version may suggest code that does not compile on the project's current SDK. Keeping the version context in the rule prevents the assistant from suggesting syntax the project cannot yet use.
When the project adds a new platform target — desktop or web, for example — review existing rules for mobile-specific assumptions. A widget structure rule written for phone screens may need a note about how it adapts to larger displays or pointer input. Platform-aware rules help the assistant produce code that works across all your active targets without hardcoding assumptions from the primary one. A brief review when targets change costs much less than fixing platform-specific issues after they reach users.