A practical guide to Flutter Clean Architecture
Clean Architecture is most useful when business rules need to survive changes to your UI or data source. Its defining feature is dependency direction, not the number of directories. A shopping app can change from an HTTP API to a local cache without rewriting checkout rules if those rules depend on an interface.
How the pieces connect
A starting folder structure
lib/
features/checkout/
presentation/checkout_page.dart
domain/place_order.dart
domain/order_repository.dart
data/api_order_repository.dart
core/dependency_injection/container.dartFollow one operation through the layers
A page sends a checkout action to a BLoC or notifier. The state owner invokes PlaceOrder with validated input. PlaceOrder depends on OrderRepository, a domain interface. The data implementation translates API responses into domain values. The composition root creates these objects and supplies the implementation; the domain never imports Dio or Flutter widgets.
Start with boundaries you can test
Test the order total, unavailable inventory, and retry policy using a fake repository. Widget tests should assert loading, success, and error rendering. Integration tests cover the real serialization and API contract. This separation gives failures a location and keeps business tests fast.
When the extra layers pay off
Use this approach for offline synchronization, multiple data sources, substantial business rules, or teams that work independently on features. A prototype displaying one endpoint may be better served by feature-first folders and a repository. Add a use case when it coordinates rules; a class that only forwards one call may add little value.
Avoid DTOs escaping into widgets
API models describe the remote contract and may contain nullable or transport-specific fields. Translate them at the data boundary. Keep errors meaningful: a domain failure such as out-of-stock should not be reduced to a generic HTTP exception. Do not make presentation construct concrete remote repositories.
Try this configuration
Clean Architecture · BLoC · Dio · GetIt · GoRouter
The generator includes a working counter example with a repository contract, selected dependencies, navigation, and local setup instructions. Extend the example around your own domain before shipping.
Configure your Flutter project →Continue reading
- BLoC vs Riverpod: choose by how your team works
- A maintainable GetX project structure
- Structure a Flutter Riverpod application
Primary references
Flutter application architecture documentation explains architectural recommendations. For state APIs, consult Riverpod documentation and BLoC documentation.