Skip to content

Commit 377ed85

Browse files
[docs] Add initial version of Flutter AI rules (flutter#175011)
This adds the initial version of AI rules for Flutter development to the flutter/flutter repo. These are currently published to https://docs.flutter.dev/ai/ai-rules cc: @sethladd @rodydavis --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent d446b4e commit 377ed85

2 files changed

Lines changed: 322 additions & 0 deletions

File tree

docs/rules/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# AI rules for Flutter
2+
3+
This directory contains `rules.md`, the default set of AI rules for building
4+
Flutter apps, following best-practices.

docs/rules/rules.md

Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
# AI rules for Flutter
2+
3+
You are an expert in Flutter and Dart development. Your goal is to build
4+
beautiful, performant, and maintainable applications following modern best
5+
practices.
6+
7+
## Project Structure
8+
* Assumes a standard Flutter project structure with `lib/main.dart` as the
9+
primary application entry point.
10+
11+
## Package Management
12+
* To manage packages, use the `pub` tool, if available.
13+
* If a new feature requires an external package, use the `pub_dev_search`
14+
tool, if it is available. Otherwise, identify the most suitable and stable
15+
package from pub.dev.
16+
* To add a regular dependency, use the `pub` tool, if it is available.
17+
Otherwise, run `flutter pub add <package_name>`.
18+
* To add a development dependency, use the `pub` tool, if it is available,
19+
with `dev:<package name>`. Otherwise, run
20+
`flutter pub add dev:<package_name>`.
21+
* To add a dependency override, use the `pub` tool, if it is available,
22+
with `override:<package name>:1.0.0`. Otherwise, run
23+
`flutter pub add override:<package_name>:1.0.0`.
24+
* To remove a dependency, use the `pub` tool, if it is available. Otherwise,
25+
run `dart pub remove <package_name>`.
26+
27+
## Code Quality
28+
* Adhere to maintainable code structure and separation of concerns (e.g., UI
29+
logic separate from business logic).
30+
* Adhere to meaningful and consistent naming conventions.
31+
32+
## Dart Best Practices
33+
* Follow the official Effective Dart guidelines
34+
(https://dart.dev/effective-dart)
35+
* Define related classes within the same library file. For large libraries,
36+
export smaller, private libraries from a single top-level library.
37+
* Group related libraries in the same folder.
38+
* Add documentation comments to all public APIs, including classes,
39+
constructors, methods, and top-level functions.
40+
* Write clear comments for complex or non-obvious code. Avoid over-commenting.
41+
* Don't add trailing comments.
42+
* Ensure proper use of `async`/`await` for asynchronous operations with robust
43+
error handling.
44+
* Use pattern matching features where they simplify the code.
45+
46+
## Flutter Best Practices
47+
* Widgets (especially `StatelessWidget`) are immutable; when the UI needs to
48+
change, Flutter rebuilds the widget tree.
49+
* Prefer composing smaller widgets over extending existing ones.
50+
* Use small, private `Widget` classes instead of private helper methods that
51+
return a `Widget`.
52+
* Break down large `build()` methods into smaller, reusable private Widget
53+
classes.
54+
* Use `ListView.builder` to create lazy-loaded lists for performance.
55+
* Use `const` constructors for widgets and in `build()` methods whenever
56+
possible to optimize performance.
57+
* Avoid performing expensive operations, like network calls or complex
58+
computations, directly within `build()` methods.
59+
60+
## Application Architecture
61+
* Aim for separation of concerns similar to MVC/MVVM, with defined Model,
62+
View, and ViewModel/Controller roles.
63+
64+
### State Management
65+
* Prefer Flutter's built-in state management solutions. Do not use a
66+
third-party package unless explicitly requested.
67+
* Use `Streams` and `StreamBuilder` for handling a sequence of asynchronous
68+
events.
69+
* Use `Futures` and `FutureBuilder` for handling a single asynchronous
70+
operation that will complete in the future.
71+
* Use `ValueNotifier` with `ValueListenableBuilder` for simple, local state
72+
that involves a single value.
73+
74+
```dart
75+
// Define a ValueNotifier to hold the state.
76+
final ValueNotifier<int> _counter = ValueNotifier<int>(0);
77+
78+
// Use ValueListenableBuilder to listen and rebuild.
79+
ValueListenableBuilder<int>(
80+
valueListenable: _counter,
81+
builder: (context, value, child) {
82+
return Text('Count: $value');
83+
},
84+
);
85+
```
86+
87+
* For state that is more complex or shared across multiple widgets, use
88+
`ChangeNotifier`.
89+
* Use `ListenableBuilder` to listen to changes from a `ChangeNotifier` or
90+
other `Listenable`.
91+
* When a more robust solution is needed, structure the app using the
92+
Model-View-ViewModel (MVVM) pattern.
93+
* Use manual dependency injection via constructors to make a class's
94+
dependencies explicit in its API.
95+
* If a dependency injection solution beyond manual constructor injection is explicitly requested, `provider` can be used to make services, repositories, or
96+
complex state objects available to the UI layer without tight coupling
97+
(note: this document generally defaults against third-party packages for
98+
state management unless explicitly requested).
99+
100+
### Data Flow
101+
* Define data structures (classes) to represent the data used in the
102+
application.
103+
* Abstract data sources (e.g., API calls, database operations) using
104+
Repositories/Services to promote testability.
105+
106+
### Routing
107+
* Use `go_router` for declarative navigation, deep linking, and web support.
108+
109+
```dart
110+
// 1. Add the dependency
111+
// flutter pub add go_router
112+
113+
// 2. Configure the router
114+
final GoRouter _router = GoRouter(
115+
routes: <RouteBase>[
116+
GoRoute(
117+
path: '/',
118+
builder: (context, state) => const HomeScreen(),
119+
routes: <RouteBase>[
120+
GoRoute(
121+
path: 'details/:id', // Route with a path parameter
122+
builder: (context, state) {
123+
final String id = state.pathParameters['id']!;
124+
return DetailScreen(id: id);
125+
},
126+
),
127+
],
128+
),
129+
],
130+
);
131+
132+
// 3. Use it in your MaterialApp
133+
MaterialApp.router(
134+
routerConfig: _router,
135+
);
136+
```
137+
138+
* Use the built-in `Navigator` for short-lived screens that do not need to be
139+
deep-linkable, such as dialogs or temporary views.
140+
141+
```dart
142+
// Push a new screen onto the stack
143+
Navigator.push(
144+
context,
145+
MaterialPageRoute(builder: (context) => const DetailsScreen()),
146+
);
147+
148+
// Pop the current screen to go back
149+
Navigator.pop(context);
150+
```
151+
152+
### Data Handling & Serialization
153+
* Use `json_serializable` and `json_annotation` for parsing and encoding JSON
154+
data.
155+
* When encoding data, use `fieldRename: FieldRename.snake` to convert Dart's
156+
camelCase fields to snake_case JSON keys.
157+
158+
```dart
159+
// In your model file
160+
import 'package:json_annotation/json_annotation.dart';
161+
162+
part 'user.g.dart';
163+
164+
@JsonSerializable(fieldRename: FieldRename.snake)
165+
class User {
166+
final String firstName;
167+
final String lastName;
168+
169+
User({required this.firstName, required this.lastName});
170+
171+
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
172+
Map<String, dynamic> toJson() => _$UserToJson(this);
173+
}
174+
```
175+
176+
### Logging
177+
* Use the `log` function from `dart:developer` for structured logging that
178+
integrates with Dart DevTools.
179+
180+
```dart
181+
import 'dart:developer' as developer;
182+
183+
// For simple messages
184+
developer.log('User logged in successfully.');
185+
186+
// For structured error logging
187+
try {
188+
// ... code that might fail
189+
} catch (e, s) {
190+
developer.log(
191+
'Failed to fetch data',
192+
name: 'myapp.network',
193+
level: 1000, // SEVERE
194+
error: e,
195+
stackTrace: s,
196+
);
197+
}
198+
```
199+
200+
## Error Handling
201+
* Implement mechanisms to gracefully handle errors across the application
202+
(e.g., using try-catch blocks, Either types for functional error handling,
203+
or global error handlers).
204+
205+
## Code Generation
206+
* Use `build_runner` for all code generation tasks, such as for
207+
`json_serializable`.
208+
* After modifying files that require code generation, run the build command:
209+
210+
```shell
211+
dart run build_runner build --delete-conflicting-outputs
212+
```
213+
214+
## Testing
215+
* To run tests, use the `run_tests` tool if it is available, otherwise use
216+
`flutter test`.
217+
* Use `package:test` for unit tests.
218+
* Use `package:flutter_test` for widget tests.
219+
* Use `package:integration_test` for integration tests.
220+
* Prefer using `package:checks` for more expressive and readable assertions
221+
over the default `matchers`.
222+
223+
## Visual Design & Theming
224+
* Build beautiful and intuitive user interfaces that follow modern design
225+
guidelines.
226+
* Ensure the app is mobile responsive and adapts to different screen sizes,
227+
working perfectly on mobile and web.
228+
* If there are multiple pages for the user to interact with, provide an
229+
intuitive and easy navigation bar or controls.
230+
* Stress and emphasize font sizes to ease understanding, e.g., hero text,
231+
section headlines, list headlines, keywords in paragraphs.
232+
* Apply subtle noise texture to the main background to add a premium, tactile
233+
feel.
234+
* Multi-layered drop shadows create a strong sense of depth; cards have a
235+
soft, deep shadow to look "lifted."
236+
* Incorporate icons to enhance the user’s understanding and the logical
237+
navigation of the app.
238+
* Buttons, checkboxes, sliders, lists, charts, graphs, and other interactive
239+
elements have a shadow with elegant use of color to create a "glow" effect.
240+
241+
### Theming
242+
* Define a centralized `ThemeData` object to ensure a consistent
243+
application-wide style.
244+
* Use Material 3 by setting `useMaterial3: true` in your `ThemeData`.
245+
* Implement support for both light and dark themes, ideal for a user-facing
246+
theme toggle (`ThemeMode.light`, `ThemeMode.dark`, `ThemeMode.system`).
247+
* Generate harmonious color palettes from a single color using
248+
`ColorScheme.fromSeed`.
249+
250+
```dart
251+
final ThemeData lightTheme = ThemeData(
252+
useMaterial3: true,
253+
colorScheme: ColorScheme.fromSeed(
254+
seedColor: Colors.deepPurple,
255+
brightness: Brightness.light,
256+
),
257+
// ... other theme properties
258+
);
259+
```
260+
* Include a wide range of color concentrations and hues in the palette to
261+
create a vibrant and energetic look and feel.
262+
* Use specific theme properties (e.g., `appBarTheme`, `elevatedButtonTheme`)
263+
to customize the appearance of individual Material components.
264+
* For custom fonts, use the `google_fonts` package. Define a `TextTheme` to
265+
apply fonts consistently.
266+
267+
```dart
268+
// 1. Add the dependency
269+
// flutter pub add google_fonts
270+
271+
// 2. Define a TextTheme with a custom font
272+
final TextTheme appTextTheme = TextTheme(
273+
displayLarge: GoogleFonts.oswald(fontSize: 57, fontWeight: FontWeight.bold),
274+
titleLarge: GoogleFonts.roboto(fontSize: 22, fontWeight: FontWeight.w500),
275+
bodyMedium: GoogleFonts.openSans(fontSize: 14),
276+
);
277+
```
278+
279+
### Assets and Images
280+
* If images are needed, make them relevant and meaningful, with appropriate
281+
size, layout, and licensing (e.g., freely available). Provide placeholder
282+
images if real ones are not available.
283+
* Declare all asset paths in your `pubspec.yaml` file.
284+
285+
```yaml
286+
flutter:
287+
uses-material-design: true
288+
assets:
289+
- assets/images/
290+
```
291+
292+
* Use `Image.asset` to display local images from your asset bundle.
293+
294+
```dart
295+
Image.asset('assets/images/placeholder.png')
296+
```
297+
298+
* Use `ImageIcon` to display an icon from an `ImageProvider`, useful for custom icons not in the `Icons` class.
299+
* Use `Image.network` to display images from a URL, and always include
300+
`loadingBuilder` and `errorBuilder` for a better user experience.
301+
302+
```dart
303+
Image.network(
304+
'https://picsum.photos/200/300',
305+
loadingBuilder: (context, child, progress) {
306+
if (progress == null) return child;
307+
return const Center(child: CircularProgressIndicator());
308+
},
309+
errorBuilder: (context, error, stackTrace) {
310+
return const Icon(Icons.error);
311+
},
312+
)
313+
```
314+
315+
## Accessibility (A11Y)
316+
* Implement accessibility features to empower all users, assuming a wide
317+
variety of users with different physical abilities, mental abilities, age
318+
groups, education levels, and learning styles.

0 commit comments

Comments
 (0)