## Why Choose Clean Architecture in Flutter with Feature-First and BLoC?
Developing Flutter applications that scale and remain maintainable requires a solid architectural foundation. Clean Architecture separates concerns into distinct layers—presentation, domain, and data—ensuring your app is testable, independent of frameworks, and adaptable to changes. This approach shines in complex apps like e-commerce platforms or social media feeds where features evolve independently.
The template we're exploring adopts a **feature-first** organization by default, grouping code by business features (e.g., authentication, user profile) rather than layers. This contrasts with traditional layer-first setups, making it easier to locate and manage feature-specific code in large projects. State management leverages **BLoC (Business Logic Component)**, a reactive pattern that's predictable, testable, and integrates seamlessly with Flutter's widget tree.
For reference, the complete implementation is available at [this GitHub repository](https://github.com/speedyghost/flutter-clean-architecture-feature-first-bloc). Clone it to kickstart your project: `git clone https://github.com/speedyghost/flutter-clean-architecture-feature-first-bloc.git`.
In real-world scenarios, imagine building a fitness tracking app. Features like workout logging, progress charts, and user settings can each live in isolated modules, reducing merge conflicts and speeding up onboarding for new developers.
## Core Project Structure: Feature-First Breakdown
The template structures your app around features, each containing all necessary layers. Here's the high-level directory layout:
```
lib/
├── core/
│ ├── error/
│ ├── usecase/
│ └── ...
├── features/
│ ├── auth/
│ │ ├── data/
│ │ │ ├── datasources/
│ │ │ ├── models/
│ │ │ └── repositories/
│ │ ├── domain/
│ │ │ ├── entities/
│ │ │ ├── repositories/
│ │ │ └── usecases/
│ │ └── presentation/
│ │ ├── bloc/
│ │ ├── pages/
│ │ └── widgets/
│ ├── home/
│ └── ...
└── ...
```
- **core/**: Shared utilities, errors, and base classes used across features.
- **features/**: Modular feature folders. Each includes:
- **data/**: Remote/local data sources, models, and implementations.
- **domain/**: Pure business logic—entities, abstract repositories, use cases.
- **presentation/**: UI, BLoC cubits/blocks, pages, and widgets.
This setup enforces dependency inversion: UI depends on domain, which doesn't know about data sources. In practice, for a news app, the `news` feature handles fetching articles via API (data layer), processing them into domain entities (like `Article`), and exposing states via BLoC to the UI.
## Switching to Layer-First Organization
Prefer organizing by layers across the app? The template supports toggling effortlessly:
1. Update `lib/main.dart` to import layer-first barrels instead of feature ones.
2. Modify `pubspec.yaml` if needed for build runners.
3. Run `flutter pub get` and regenerate code.
Layer-first looks like:
```
lib/
├── data/
├── domain/
└── presentation/
└── features/
```
This is ideal for smaller apps or when layers have heavy sharing. A banking app might use layer-first for centralized data mappers, while feature-first suits micro-frontends-like modularity.
## Setting Up and Generating New Features
Bootstrap quickly:
1. Clone the repo: `git clone https://github.com/speedyghost/flutter-clean-architecture-feature-first-bloc.git my_app`.
2. `cd my_app && flutter pub get`.
3. Run `flutter pub run build_runner build` for code generation (Freezed, JSON serialization).
4. Launch with `flutter run`.
To add a new feature, say `cart` for an e-commerce app:
```
mkdir -p lib/features/cart/{data/{datasources,models,repositories},domain/{entities,repositories,usecases},presentation/{bloc,pages,widgets}}
```
Implement:
- Domain: Define `CartEntity`, `CartRepository` abstract, `AddToCart` use case.
- Data: Concrete repo with `CartRemoteDataSource`, models from JSON.
- Presentation: `CartBloc` handling events like `AddItem`, states like `CartLoaded`.
Example BLoC snippet for `cart`:
```dart
import 'package:bloc/bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'cart_event.dart';
part 'cart_state.dart';
class CartBloc extends Bloc<CartEvent, CartState> {
final CartRepository repository;
CartBloc(this.repository) : super(CartInitial()) {
on<AddToCart>((event, emit) async {
emit(CartLoading());
final result = await repository.addToCart(event.item);
result.fold(
(failure) => emit(CartError(failure)),
(cart) => emit(CartLoaded(cart)),
);
});
}
}
```
Use `flutter pub run build_runner build --delete-conflicting-outputs` after changes.
## Included Features and Real-World Examples
The template ships with ready-to-use features:
- **Auth**: Login/signup with validation, token storage. BLoC manages `AuthState` (logged in/out). Real-world: Secure user sessions in a delivery app.
```dart
// Auth use case example
class LoginUser implements UseCase<AuthEntity, LoginParams> {
final AuthRepository repository;
@override
Future<Either<Failure, AuthEntity>> call(LoginParams params) async =>
await repository.login(params.email, params.password);
}
```
- **Home**: Dashboard with navigation. Demonstrates routing between features.
- **Profile/Splash/Onboarding**: Full CRUD examples with local/remote sync.
Each uses **Dartz** for `Either<Failure, Success>`, **Freezed** for immutable states/events, and **injectable** for DI.
In a ride-sharing app, extend `auth` for social logins, add `ride_request` feature mirroring this pattern—data fetches from Firebase, domain validates rules, BLoC emits UI states.
## Dependencies and Best Practices
Key packages:
| Package | Purpose | Version Note |
|---------|---------|--------------|
| flutter_bloc | Reactive state | Latest |
| injectable | DI container | With code gen |
| freezed | Immutables | For states/events |
| dartz | Functional error handling | Core for usecases |
| equatable | Value equality | Bloc states |
**Pro Tips**:
- Always inject repositories into BLoCs via `get_it`.
- Unit test use cases/domain first—they're pure.
- Mock data sources for integration tests.
- Handle failures globally in `core/error/failures.dart`.
For CI/CD, add GitHub Actions from the repo's `.github/workflows/`.
## Testing and Scalability
Clean Arch excels in testing:
- **Unit**: Domain use cases (e.g., `bloc_test` for BLoCs).
- **Widget**: `flutter_test` with mocked BLoCs.
- **Integration**: Golden tests for pages.
Scale to enterprise: Features stay isolated, enabling team ownership (one team per feature). Migrate data sources without UI changes.
## Advanced Customizations
- **Theming**: `core/theme/` for light/dark modes.
- **Navigation**: GoRouter with feature guards.
- **Internationalization**: Easy via `intl`.
Extend for push notifications: New `notifications` feature with Firebase Messaging in data layer.
This template isn't just code—it's a blueprint for production Flutter apps handling millions of users, proven in patterns from [Bloc library](https://github.com/felangel/bloc).
Word count: ~1250. Dive in, adapt, and build maintainable Flutter masterpieces!
<div style="text-align: center; margin-top: 2rem;">
<a href="https://cursor.directory/flutter-clean-architecture-feature-first-bloc" target="_blank" rel="noopener noreferrer" class="view-full-resource-btn" style="display: inline-block; background-color: #f97316; color: white; padding: 12px 24px; border-radius: 8px; text-decoration: none; font-weight: 600; transition: background-color 0.2s;">View Full Resource</a>
</div>