Flutter Clean Architecture
A comprehensive skill for building Flutter applications following Clean Architecture principles, based on real-world production patterns.
When to Use This Skill
- •Creating a new Flutter project with clean architecture
- •Setting up Dio networking with interceptors (auth, logging)
- •Implementing BLoC/Cubit state management pattern
- •Configuring dependency injection with GetIt
- •Setting up GoRouter navigation
- •Managing environment variables with flutter_dotenv
- •Implementing secure storage for tokens
- •Setting up Android/iOS permissions and security
- •Working with code generation (freezed, json_serializable)
Decision Tree - What Are You Implementing?
Use this decision tree to find the right guide for your task:
What are you implementing?
│
├── 🆕 New Flutter Project
│ ├── Project structure → See [Project Structure](examples/project-structure.md)
│ ├── Dependencies → See [pubspec Template](resources/pubspec-template.yaml)
│ ├── Environment setup → See [Environment Setup](resources/environment-setup.md)
│ └── Native splash → See [Native Splash Setup](examples/native-splash-setup.md)
│
├── 📡 API / Networking
│ ├── Dio client setup → See [Dio Setup](examples/dio-setup.md)
│ ├── Remote data source → See [Remote DataSource Pattern](examples/remote-datasource-pattern.md)
│ └── Repository layer → See [Repository Pattern](examples/repository-pattern.md)
│
├── 📦 Models / Data
│ ├── Model with freezed → See [Freezed & JSON Serializable](examples/freezed-json-serializable.md)
│ ├── Request/Response models → See [Repository Pattern](examples/repository-pattern.md)
│ └── Build runner commands → See [Build Runner Guide](examples/build-runner-guide.md)
│
├── 🔄 State Management
│ ├── Cubit pattern → See [BLoC/Cubit Example](examples/bloc-cubit-example.md)
│ ├── BLoC pattern → See [BLoC/Cubit Example](examples/bloc-cubit-example.md)
│ └── State with freezed → See [Freezed & JSON Serializable](examples/freezed-json-serializable.md)
│
├── 💉 Dependency Injection
│ └── GetIt setup → See [Dependency Injection](examples/dependency-injection.md)
│
├── 🧭 Navigation
│ └── GoRouter setup → See [Navigation Setup](examples/navigation-setup.md)
│
├── 📱 Platform Config
│ ├── Android permissions → See [Android Permissions](resources/android-permissions.md)
│ ├── iOS permissions → See [iOS Permissions](resources/ios-permissions.md)
│ └── Security checklist → See [Security Checklist](resources/security-checklist.md)
│
└── 🛠️ Code Generation
├── Freezed models → See [Freezed & JSON Serializable](examples/freezed-json-serializable.md)
├── JSON serializable → See [Freezed & JSON Serializable](examples/freezed-json-serializable.md)
└── Build runner → See [Build Runner Guide](examples/build-runner-guide.md)
Project Structure Overview
lib/ ├── main.dart # Entry point ├── app_root.dart # App root with MaterialApp ├── app_providers.dart # Global BLoC providers ├── core/ # Core utilities (environment, theme, widgets) ├── utils/ # Helpers, extensions, validators ├── data/ │ ├── data_sources/ │ │ ├── api/ # Dio, interceptors, api_path │ │ ├── local/ # SharedPreferences, SecureStorage │ │ └── remote/ # Feature data sources │ ├── models/ # Data models │ └── repositories/ # Repository implementations ├── model_view/ # BLoC/Cubit state management ├── views/ # UI pages ├── di/ # Dependency injection └── route/ # Navigation
For full structure details → See Project Structure
Quick Reference
Adding a New Feature
- •
Create model in
data/models/[feature]/→ See Freezed & JSON Serializable - •
Create remote data source in
data/data_sources/remote/→ See Remote DataSource Pattern - •
Create repository in
data/repositories/[feature]/→ See Repository Pattern - •
Create cubit in
model_view/[feature]/→ See BLoC/Cubit Example - •
Create page in
views/[feature]/ - •
Register in DI in
di/[feature]_inject.dart→ See Dependency Injection - •
Add route in
route/app_route.dart→ See Navigation Setup
Common Commands
# Code generation flutter pub run build_runner build --delete-conflicting-outputs # Watch mode (development) flutter pub run build_runner watch --delete-conflicting-outputs # Generate native splash flutter pub run flutter_native_splash:create
For more commands → See Build Runner Guide
Examples & Resources
Examples
- •Project Structure - Complete project structure details
- •Dio Setup - DioClient with interceptors
- •BLoC/Cubit Example - State management pattern
- •Repository Pattern - Repository implementation
- •Remote DataSource Pattern - Remote data source layer
- •Dependency Injection - GetIt DI setup
- •Navigation Setup - GoRouter configuration
- •Native Splash Setup - flutter_native_splash configuration
- •Freezed & JSON Serializable - Code generation for models
- •Build Runner Guide - Build runner commands and tips
Resources
- •pubspec Template - Complete pubspec.yaml
- •Android Permissions - AndroidManifest setup
- •iOS Permissions - Info.plist setup
- •Environment Setup - Multi-environment config
- •Security Checklist - Security best practices
Best Practices
Naming Conventions
- •Files:
snake_case.dart - •Classes:
PascalCase - •Variables/Functions:
camelCase
Layer Dependencies
views → model_view → data/repositories → data/data_sources
↘ core (utilities)
State Management
- •Use
Cubitfor simple state - •Use
BLoCfor complex event-driven state - •Always use
freezedfor state classes
Error Handling
- •Use
Either<Failure, Success>from dartz - •Define specific
Failuretypes - •Handle network errors gracefully
Troubleshooting
| Issue | Solution | Reference |
|---|---|---|
| Token refresh loop | Check DioAuthInterceptor logic | Dio Setup |
| State not updating | Ensure Equatable props are correct | BLoC/Cubit Example |
| DI not found | Verify registration order | Dependency Injection |
| Build runner errors | Run flutter clean && flutter pub get | Build Runner Guide |
| Part file not found | Check part directive matches filename | Freezed Guide |