---
description: "BLoC / Cubit conventions for {{PROJECT_NAME}}"
alwaysApply: true
---

# BLoC / Cubit Standards — {{PROJECT_NAME}}

## When to use BLoC vs Cubit
- **Cubit**: simple state with no meaningful event history (toggle, counter, pagination)
- **BLoC**: event-driven flows where event history or transitions matter (auth, checkout, form wizard)

## Event and State classes
```dart
// Events — sealed class (exhaustive switch)
sealed class AuthEvent { const AuthEvent(); }
final class AuthLoginRequested extends AuthEvent {
  final String email, password;
  const AuthLoginRequested({required this.email, required this.password});
}
final class AuthLogoutRequested extends AuthEvent { const AuthLogoutRequested(); }

// States — sealed class, immutable
sealed class AuthState { const AuthState(); }
final class AuthInitial         extends AuthState { const AuthInitial(); }
final class AuthLoading         extends AuthState { const AuthLoading(); }
final class AuthAuthenticated   extends AuthState {
  final User user;
  const AuthAuthenticated(this.user);
}
final class AuthUnauthenticated extends AuthState { const AuthUnauthenticated(); }
final class AuthFailure         extends AuthState {
  final String message;
  const AuthFailure(this.message);
}
```

## BlocProvider placement
- Create `BlocProvider` at the **route level** (in {{ROUTING}} route definitions)
- `MultiBlocProvider` at route level for screens needing multiple blocs
- **NEVER** create `BlocProvider` inside a widget's `build()` method

## Usage rules
- **NEVER** call `bloc.add()` inside `build()` — only in gesture callbacks or `initState()`
- Use `BlocConsumer` only when BOTH `listen` + `build` logic are needed
- Use `BlocSelector` when only a subset of state triggers a rebuild
- Every BLoC must override `close()` and cancel `StreamSubscription`s

## BlocBuilder patterns
```dart
BlocBuilder<AuthBloc, AuthState>(
  builder: (context, state) => switch (state) {
    AuthInitial()         => const SizedBox.shrink(),
    AuthLoading()         => const LoadingIndicator(),
    AuthAuthenticated(user: final u) => HomeScreen(user: u),
    AuthUnauthenticated() => const LoginScreen(),
    AuthFailure(message: final m)    => ErrorScreen(message: m),
  },
)
```

## File locations in {{PROJECT_NAME}}
- `lib/features/[feature]/presentation/bloc/[feature]_bloc.dart`
- `lib/features/[feature]/presentation/bloc/[feature]_event.dart`
- `lib/features/[feature]/presentation/bloc/[feature]_state.dart`
