mirror of
https://github.com/kuhyx/todo-app.git
synced 2026-11-10 19:07:02 +01:00
Renames this repo's markdown onto README.md / CLAUDE*.md / DOCS*.md / TODO*.md so a future session can tell a live task from a finished record without reading the file to find out. TODO files carry the literal "REMOVE ME AFTER FINISH" and are deleted when the work lands. Enforced by the md-naming pre-commit hook and CI workflow, both delegating to the shared gate in kuhyx/utils so this repo's idea of a valid name cannot drift from every other repo's. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A47aX5DJwmA3QFn3pkEWi7
155 lines
5.1 KiB
Markdown
155 lines
5.1 KiB
Markdown
# Flutter AI rules — state, routing and data
|
|
|
|
State management, data flow, routing, JSON serialization and logging.
|
|
|
|
_Verbatim from [flutter/flutter docs/rules/rules.md](https://github.com/flutter/flutter/blob/main/docs/rules/rules.md), split across four files only to keep each under the repo's 250-line
|
|
cap. Re-fetch periodically to stay current; do not hand-edit._
|
|
|
|
#### State Management
|
|
* **Built-in Solutions:** Prefer Flutter's built-in state management solutions.
|
|
Do not use a third-party package unless explicitly requested.
|
|
* **Streams:** Use `Streams` and `StreamBuilder` for handling a sequence of
|
|
asynchronous events.
|
|
* **Futures:** Use `Futures` and `FutureBuilder` for handling a single
|
|
asynchronous operation that will complete in the future.
|
|
* **ValueNotifier:** Use `ValueNotifier` with `ValueListenableBuilder` for
|
|
simple, local state that involves a single value.
|
|
|
|
```dart
|
|
// Define a ValueNotifier to hold the state.
|
|
final ValueNotifier<int> _counter = ValueNotifier<int>(0);
|
|
|
|
// Use ValueListenableBuilder to listen and rebuild.
|
|
ValueListenableBuilder<int>(
|
|
valueListenable: _counter,
|
|
builder: (context, value, child) {
|
|
return Text('Count: $value');
|
|
},
|
|
);
|
|
```
|
|
|
|
* **ChangeNotifier:** For state that is more complex or shared across multiple
|
|
widgets, use `ChangeNotifier`.
|
|
* **ListenableBuilder:** Use `ListenableBuilder` to listen to changes from a
|
|
`ChangeNotifier` or other `Listenable`.
|
|
* **MVVM:** When a more robust solution is needed, structure the app using the
|
|
Model-View-ViewModel (MVVM) pattern.
|
|
* **Dependency Injection:** Use simple manual constructor dependency injection
|
|
to make a class's dependencies explicit in its API, and to manage dependencies
|
|
between different layers of the application.
|
|
* **Provider:** If a dependency injection solution beyond manual constructor
|
|
injection is explicitly requested, `provider` can be used to make services,
|
|
repositories, or complex state objects available to the UI layer without tight
|
|
coupling (note: this document generally defaults against third-party packages
|
|
for state management unless explicitly requested).
|
|
|
|
#### Data Flow
|
|
* **Data Structures:** Define data structures (classes) to represent the data
|
|
used in the application.
|
|
* **Data Abstraction:** Abstract data sources (e.g., API calls, database
|
|
operations) using Repositories/Services to promote testability.
|
|
|
|
#### Routing
|
|
* **GoRouter:** Use the `go_router` package for declarative navigation, deep
|
|
linking, and web support.
|
|
* **GoRouter Setup:** To use `go_router`, first add it to your `pubspec.yaml`
|
|
using the `pub` tool's `add` command.
|
|
|
|
```dart
|
|
// 1. Add the dependency
|
|
// flutter pub add go_router
|
|
|
|
// 2. Configure the router
|
|
final GoRouter _router = GoRouter(
|
|
routes: <RouteBase>[
|
|
GoRoute(
|
|
path: '/',
|
|
builder: (context, state) => const HomeScreen(),
|
|
routes: <RouteBase>[
|
|
GoRoute(
|
|
path: 'details/:id', // Route with a path parameter
|
|
builder: (context, state) {
|
|
final String id = state.pathParameters['id']!;
|
|
return DetailScreen(id: id);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
],
|
|
);
|
|
|
|
// 3. Use it in your MaterialApp
|
|
MaterialApp.router(
|
|
routerConfig: _router,
|
|
);
|
|
```
|
|
* **Authentication Redirects:** Configure `go_router`'s `redirect` property to
|
|
handle authentication flows, ensuring users are redirected to the login screen
|
|
when unauthorized, and back to their intended destination after successful
|
|
login.
|
|
|
|
* **Navigator:** Use the built-in `Navigator` for short-lived screens that do
|
|
not need to be deep-linkable, such as dialogs or temporary views.
|
|
|
|
```dart
|
|
// Push a new screen onto the stack
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(builder: (context) => const DetailsScreen()),
|
|
);
|
|
|
|
// Pop the current screen to go back
|
|
Navigator.pop(context);
|
|
```
|
|
|
|
#### Data Handling & Serialization
|
|
* **JSON Serialization:** Use `json_serializable` and `json_annotation` for
|
|
parsing and encoding JSON data.
|
|
* **Field Renaming:** When encoding data, use `fieldRename: FieldRename.snake`
|
|
to convert Dart's camelCase fields to snake_case JSON keys.
|
|
|
|
```dart
|
|
// In your model file
|
|
import 'package:json_annotation/json_annotation.dart';
|
|
|
|
part 'user.g.dart';
|
|
|
|
@JsonSerializable(fieldRename: FieldRename.snake)
|
|
class User {
|
|
final String firstName;
|
|
final String lastName;
|
|
|
|
User({required this.firstName, required this.lastName});
|
|
|
|
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
|
|
Map<String, dynamic> toJson() => _$UserToJson(this);
|
|
}
|
|
```
|
|
|
|
|
|
#### Logging
|
|
* **Structured Logging:** Use the `log` function from `dart:developer` for
|
|
structured logging that integrates with Dart DevTools.
|
|
|
|
```dart
|
|
import 'dart:developer' as developer;
|
|
|
|
// For simple messages
|
|
developer.log('User logged in successfully.');
|
|
|
|
// For structured error logging
|
|
try {
|
|
// ... code that might fail
|
|
} catch (e, s) {
|
|
developer.log(
|
|
'Failed to fetch data',
|
|
name: 'myapp.network',
|
|
level: 1000, // SEVERE
|
|
error: e,
|
|
stackTrace: s,
|
|
);
|
|
}
|
|
```
|
|
|
|
### Code Generation
|