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 │ ├── Dependencies → See pubspec Template │ ├── Environment setup → See Environment Setup │ └── Native splash → See Native Splash Setup │ ├── 📡 API / Networking │ ├── Dio client setup → See Dio Setup │ ├── Remote data source → See Remote DataSource Pattern │ └── Repository layer → See Repository Pattern │ ├── 📦 Models / Data │ ├── Model with freezed → See Freezed & JSON Serializable │ ├── Request/Response models → See Repository Pattern │ └── Build runner commands → See Build Runner Guide │ ├── 🔄 State Management │ ├── Cubit pattern → See BLoC/Cubit Example │ ├── BLoC pattern → See BLoC/Cubit Example │ └── State with freezed → See Freezed & JSON Serializable │ ├── 💉 Dependency Injection │ └── GetIt setup → See Dependency Injection │ ├── 🧭 Navigation │ └── GoRouter setup → See Navigation Setup │ ├── 📱 Platform Config │ ├── Android permissions → See Android Permissions │ ├── iOS permissions → See iOS Permissions │ └── Security checklist → See Security Checklist │ └── 🛠️ Code Generation ├── Freezed models → See Freezed & JSON Serializable ├── JSON serializable → See Freezed & JSON Serializable └── Build runner → See Build Runner Guide
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 Cubit for simple state
-
Use BLoC for complex event-driven state
-
Always use freezed for state classes
Error Handling
-
Use Either<Failure, Success> from dartz
-
Define specific Failure types
-
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