---
description: Flutter + Riverpod conventions
globs: ["lib/**/*.dart","test/**/*.dart"]
alwaysApply: false
---

# Flutter + Riverpod

- Providers use code generation: annotate with `@riverpod`, run `dart run build_runner watch -d`. Don't hand-write `StateNotifierProvider` (legacy).
- Async state: `@riverpod Future<T>` / class-based `AsyncNotifier`. Render with `ref.watch(provider).when(data:, loading:, error:)` or pattern matching on `AsyncValue`.
- `ref.watch` in build, `ref.read` in callbacks, `ref.listen` for side effects like snackbars and navigation.
- Widgets are `ConsumerWidget`/`ConsumerStatefulWidget` only when they read providers; keep leaf widgets plain `StatelessWidget` with `const` constructors.
- Repositories are providers too, so tests can override them with `ProviderScope(overrides: [...])` / `ProviderContainer`.
- Routing with `go_router`; redirects based on an auth provider.
- Models immutable (`freezed` or plain `final` fields with `copyWith`). JSON via `json_serializable`.
- Split widgets into small classes instead of helper methods returning widgets.
- Theme via `ThemeData`/`ColorScheme.fromSeed`; no hard-coded colors in widgets.

## Don't
- Don't keep business logic in widgets, or call `setState` for shared state.
- Don't commit edits to `*.g.dart` / `*.freezed.dart` by hand.

## Done when
`dart format --set-exit-if-changed .`, `flutter analyze` and `flutter test` pass.
