# Flutter with Dart — Cursor Rules

You are an expert Flutter developer building cross-platform mobile and web applications with Dart, following Flutter best practices and Material Design 3.

## Code Style

- Use Dart 3+ features: records, patterns, sealed classes, class modifiers (`final`, `base`, `interface`).
- Follow Effective Dart guidelines. Use `dart_style` (dartfmt) for formatting.
- Use `lowerCamelCase` for variables, functions, and parameters. `UpperCamelCase` for classes, enums, typedefs, and extensions. `lowercase_with_underscores` for file names and libraries.
- Prefer `final` over `var` for variables that don't change after initialization.
- Use `const` constructors wherever possible — it improves widget rebuild performance.
- Use type annotations for function parameters, return types, and public API. Let Dart infer types for local variables.
- Use `///` doc comments on all public classes, methods, and properties. Start with a single-sentence summary.
- Use trailing commas on all parameter lists and collection literals for consistent formatting.
- Prefer `String interpolation $variable` over concatenation.
- Run `dart analyze` with no issues before committing. Enable `strict-casts` and `strict-raw-types`.

## Widget Architecture

- Prefer composition over inheritance. Build complex UIs by combining small, focused widgets.
- Keep the `build()` method concise. Extract sub-widgets into private methods or separate widget classes.
- Use `StatelessWidget` by default. Only use `StatefulWidget` when the widget has mutable state.
- Split large widgets into smaller widgets rather than using many helper methods. Separate widget classes optimize rebuild performance.
- Use `const` constructors for widgets that don't depend on runtime data.
- Never put business logic in widgets. Widgets are for UI only.
- Use `Key` parameters when the widget tree can change (lists, conditional rendering).

## State Management

- Use Riverpod as the primary state management solution. Prefer Riverpod over Provider, BLoC, or GetX for new projects.
- Define providers outside of widgets. Use `ref.watch()` in `build()` for reactive UI, `ref.read()` for one-time reads in callbacks.
- Use `StateNotifierProvider` or `NotifierProvider` for complex state logic.
- Use `FutureProvider` for async data fetching. Use `StreamProvider` for real-time data.
- Keep state classes immutable. Use `copyWith()` for state updates.
- Use `AsyncValue` pattern for loading/error/data states. Handle all three in the UI.
- Scope providers to features. Create a `providers/` directory per feature module.

## Navigation

- Use GoRouter for declarative routing. Define routes in a central `router.dart` file.
- Use typed route parameters. Define route path constants to avoid magic strings.
- Use `context.go()` for navigation, `context.push()` for adding to the stack.
- Use shell routes for persistent bottom navigation or side navigation.
- Handle deep links by defining route patterns that match the expected URL structure.
- Use redirect guards for authentication: redirect unauthenticated users to login.
- Use `StatefulShellRoute` for tabs that preserve state across tab switches.

## Layout and Design

- Follow Material Design 3 guidelines. Use `MaterialApp` with `useMaterial3: true`.
- Use `ThemeData` with `ColorScheme.fromSeed()` for consistent theming.
- Use `LayoutBuilder` and `MediaQuery` for responsive layouts. Define breakpoints for mobile, tablet, desktop.
- Use `Flex`, `Column`, `Row`, `Expanded`, `Flexible` for layout. Avoid hardcoded sizes.
- Use `SizedBox` for spacing between widgets. Avoid `Padding` when `SizedBox` suffices.
- Use `SafeArea` to avoid system UI overlap (notches, status bar, navigation bar).
- Use `Scaffold` as the root of each screen with `AppBar`, `body`, `bottomNavigationBar`, and `floatingActionButton`.
- Extract theme-specific values from `Theme.of(context)`. Never hardcode colors, font sizes, or spacing.

## Networking

- Use `dio` for HTTP networking with interceptors for auth, logging, and error handling.
- Create a centralized API client class that configures base URL, headers, and interceptors.
- Use data classes for API responses. Parse JSON into typed Dart objects.
- Use `freezed` for immutable data classes with `fromJson`/`toJson` generated by `json_serializable`.
- Handle network errors gracefully: timeout, no connection, server errors. Show user-friendly messages.
- Use `CancelToken` to cancel requests when widgets are disposed.
- Cache API responses with an appropriate strategy (stale-while-revalidate, cache-first).

## Error Handling

- Use `sealed class` for result types: `sealed class Result<T> { Success(T data); Failure(AppException error); }`.
- Define domain-specific exception classes. Map API errors to domain exceptions in the repository layer.
- Use `try/catch` with specific exception types. Never use bare `catch`.
- Show user-friendly error messages with `SnackBar` or inline error widgets. Never show raw exception messages.
- Use `ErrorWidget.builder` for custom error widgets during development.
- Log errors with a logging framework. Include stack traces for unexpected errors.
- Use `FlutterError.onError` to capture widget build errors.

## Testing

- Use `flutter_test` for widget tests, `test` for unit tests, `integration_test` for integration tests.
- Write unit tests for business logic, state management, and data models.
- Write widget tests for UI components. Use `find.byType`, `find.text`, `find.byKey` for element queries.
- Use `tester.pumpWidget()` to render widgets, `tester.tap()` and `tester.enterText()` for interactions.
- Mock dependencies with `mocktail` or `mockito`. Create fakes for complex dependencies.
- Test all states: loading, data, error, empty.
- Achieve high test coverage on business logic. Visual components need fewer tests.
- Place tests in `test/` mirroring the `lib/` structure.

## File Structure

```
lib/
  main.dart              — Entry point, app setup
  app.dart               — MaterialApp, router, theme configuration
  core/
    theme/
      app_theme.dart     — ThemeData configuration
      colors.dart        — Color constants
    network/
      api_client.dart    — Dio client setup
      interceptors.dart  — Auth, logging interceptors
    utils/
      extensions.dart    — Dart extension methods
      validators.dart    — Input validation
    errors/
      app_exception.dart — Exception classes
      error_handler.dart — Global error handling
  features/
    auth/
      data/
        auth_repository.dart
        models/user_model.dart
      presentation/
        screens/login_screen.dart
        widgets/login_form.dart
        providers/auth_provider.dart
    home/
      data/
      presentation/
        screens/home_screen.dart
        widgets/
        providers/
  shared/
    widgets/              — Reusable UI components
      app_button.dart
      loading_indicator.dart
      error_view.dart
    providers/            — App-wide providers
  router/
    app_router.dart      — GoRouter configuration
    routes.dart          — Route constants
test/
  features/
    auth/
      auth_repository_test.dart
      login_screen_test.dart
integration_test/
  app_test.dart
```

## Performance

- Use `const` constructors aggressively. Every `const` widget avoids unnecessary rebuilds.
- Use `ListView.builder` for long lists (not `ListView` with `children`). This builds items lazily.
- Use `RepaintBoundary` to isolate frequently updated widgets from the rest of the tree.
- Profile with Flutter DevTools. Check for jank, excessive rebuilds, and memory leaks.
- Use `compute()` for expensive computations to run them on a separate isolate.
- Optimize images: use appropriate resolution, cache network images with `cached_network_image`.
- Minimize widget tree depth. Flatter trees rebuild faster.
- Use `AutomaticKeepAliveClientMixin` for tab views that should preserve state.

## Security

- Store sensitive data (tokens, keys) with `flutter_secure_storage`. Never use SharedPreferences for secrets.
- Use HTTPS for all network requests. Pin certificates in production if handling sensitive data.
- Validate all user input on both client and server.
- Obfuscate Dart code in release builds: `flutter build --obfuscate --split-debug-info`.
- Never hardcode API keys or secrets in source code. Use `--dart-define` for build-time configuration.
- Sanitize data before displaying user-generated content.
