--- description: "Freezed code generation conventions for {{PROJECT_NAME}} — Pillar 4" alwaysApply: true --- # Freezed Standards — {{PROJECT_NAME}} ## When to use Freezed - All domain entities and data models — use `@freezed` - Union types / sealed classes — use `@freezed` with multiple constructors - BLoC states and events — use `@freezed` ## Model pattern ```dart @freezed class Product with _$Product { const factory Product({ required String id, required String name, required double price, @Default(0) int stockCount, String? imageUrl, }) = _Product; factory Product.fromJson(Map json) => _$ProductFromJson(json); } ``` ## Union type pattern ```dart @freezed sealed class ProductState with _$ProductState { const factory ProductState.initial() = ProductInitial; const factory ProductState.loading() = ProductLoading; const factory ProductState.loaded(List products) = ProductLoaded; const factory ProductState.error(String message) = ProductError; } // Usage — exhaustive switch final widget = state.when( initial: () => const SizedBox.shrink(), loading: () => const ProductShimmer(), loaded: (products) => ProductList(products: products), error: (msg) => ErrorWidget(message: msg), ); ``` ## Critical rules - **NEVER** edit `.freezed.dart` or `.g.dart` files — they are generated - Run `dart run build_runner build --delete-conflicting-outputs` after changes - Run `dart run build_runner watch` during development - Add `*.freezed.dart` and `*.g.dart` to `.gitignore` (or commit them — team must decide) - Always define `copyWith` via Freezed — never write manual `copyWith` ## Patterns to avoid ```dart // ❌ Manual copyWith — replaced by Freezed Product copyWith({String? name, double? price}) => Product( id: id, name: name ?? this.name, price: price ?? this.price, ); // ✅ Let Freezed generate it product.copyWith(name: 'New Name', price: 9.99) ```