Flutter Clean Architecture: Feature-First Organization with BLoC State Management
Discover a robust Flutter template using Clean Architecture organized by features with BLoC for scalable, testable apps. Perfect for real-world projects needing modular structure.
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. 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:
- Update
lib/main.dartto import layer-first barrels instead of feature ones. - Modify
pubspec.yamlif needed for build runners. - Run
flutter pub getand 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:
- Clone the repo:
git clone https://github.com/speedyghost/flutter-clean-architecture-feature-first-bloc.git my_app. cd my_app && flutter pub get.- Run
flutter pub run build_runner buildfor code generation (Freezed, JSON serialization). - 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,CartRepositoryabstract,AddToCartuse case. - Data: Concrete repo with
CartRemoteDataSource, models from JSON. - Presentation:
CartBlochandling events likeAddItem, states likeCartLoaded.
Example BLoC snippet for cart:
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.// 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_testfor BLoCs). - Widget:
flutter_testwith 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.
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>Comments
More Blog
View allBuilding Voice Agents with Claude API and ElevenLabs: Conversational AI Guide
Build natural voice agents combining Claude API's superior reasoning with ElevenLabs' lifelike TTS. This end-to-end guide creates a conversational web app with STT, AI chat, and speech synthesis.
Claude vs Mistral Large 2: 2025 Data Analysis Benchmarks and Use Cases
As data volumes explode in 2025, choosing between Claude's reasoning depth and Mistral Large 2's efficiency is critical. We benchmark SQL generation, visualizations, and large datasets to reveal the w
Claude Enterprise for Cybersecurity: Threat Modeling and Incident Response
In the high-stakes world of cybersecurity, rapid threat modeling and incident response can mean the difference between containment and catastrophe. Discover how Claude Enterprise empowers security tea
Claude Code in VS Code: Custom Commands for Refactoring Large Codebases
Refactoring sprawling codebases manually? Harness Claude Code's power in VS Code with custom commands to automate AI-driven refactors across TypeScript and Python projects—saving hours of drudgery.
Claude SDK Rust for Blockchain: Smart Contract Auditing Agents
Build blazing-fast smart contract auditing agents in Rust using the Claude SDK. Harness Claude's reasoning to scan Solidity code for vulnerabilities like reentrancy and overflows.
Advanced Claude Artifacts: Collaborative Editing in Multi-User Sessions
Elevate team productivity with Claude Artifacts in multi-user projects—enable real-time iterative editing for code reviews and docs without leaving the interface.