--- description: Clean Architecture + Feature-first + BLoC/Riverpod patterns for Flutter features. Apply to feature modules. globs: "lib/features/**/*.dart" --- # Flutter Clean Architecture — Feature-First ## Architecture Layers (Dependency Rule: always inward) - **Presentation** → Widgets, Screens, BLoC/Cubit, ViewModels - **Domain** → Entities, Repository interfaces, Use Cases - **Data** → Repository implementations, Data Sources, DTOs/Models ## Feature Directory Structure ``` lib/features/feature_name/ ├── data/ │ ├── datasources/ # Remote + Local data sources │ ├── models/ # DTOs, data models (with fromJson/toJson) │ └── repositories/ # Repository implementations ├── domain/ │ ├── entities/ # Pure business objects │ ├── repositories/ # Abstract repository interfaces │ └── usecases/ # Single-purpose business logic └── presentation/ ├── bloc/ # BLoC/Cubit state management ├── pages/ # Screen widgets └── widgets/ # Feature-specific widgets ``` ## Use Case Pattern ```dart abstract class UseCase { Future> call(Params params); } ``` ## State Management - Use Freezed for immutable state classes and union types. - States: initial, loading, loaded(data), error(failure). - Use BlocBuilder with buildWhen for optimized rebuilds. - Use BlocListener for side effects (navigation, dialogs). - Avoid business logic in UI components. ## Error Handling - Use Either from Dartz for functional error handling. - Create custom Failure classes per domain. - Proper error mapping between layers. - User-friendly error messages in presentation layer. ## Dependency Injection - Use GetIt as service locator. - Register dependencies by feature in separate files. - Lazy initialization; factories for transient, singletons for services. ## Repository Pattern - Single source of truth for data. - Handle network/cache fallback gracefully. - Map data models to domain entities at repository boundary. ## Constraints ### MUST DO - Use const constructors wherever possible. - Implement proper keys for lists. - Follow Material/Cupertino design guidelines. - Profile with DevTools, fix jank. - Test widgets with flutter_test. ### MUST NOT DO - Build widgets inside build() method. - Mutate state directly (always create new instances). - Use setState for app-wide state. - Block UI thread with heavy computation (use compute()). - Skip const on static widgets.