Skip to content

Flutter Boilerplate Architecture

This project follows Clean Architecture principles with a feature-based modular structure. Each feature is organized into distinct layers that promote separation of concerns, testability, and maintainability.

Project Structure Overview

lib/
├── app/                          # Application layer
│   ├── pages/                    # Global pages (home, splash)
│   ├── app.dart                  # Main app widget
│   ├── bootstrap.dart            # App initialization
│   ├── di.dart                   # Dependency injection setup
│   └── routes.dart               # App routing configuration
├── core/                         # Shared utilities and services
│   ├── error/                    # Error handling
│   ├── extensions/               # Dart extensions
│   ├── presentation/             # Shared UI components
│   ├── services/                 # Platform services
│   └── utils/                    # Utility functions
├── features/                     # Feature modules
│   └── [feature_name]/           # Individual feature
└── l10n/                         # Internationalization

Feature Architecture

Each feature follows a layered architecture pattern:

├── [feature_name]/
│   ├── data/                     # Data layer
│   │   ├── models/               # Data models (JSON serialization)
│   │   │   ├── feature_model.dart
│   │   │   ├── feature_model.freezed.dart
│   │   │   └── feature_model.g.dart
│   │   └── repositories/         # Repository implementations
│   │       └── debug_feature_repository.dart
│   ├── domain/                   # Business logic layer
│   │   ├── entities/             # Business entities
│   │   │   ├── feature_entity.dart
│   │   │   └── feature_entity.freezed.dart
│   │   └── repositories/         # Repository interfaces
│   │       └── feature_repository.dart
│   ├── presentation/             # UI layer
│   │   ├── cubit/                # State management (Cubit/Bloc)
│   │   │   ├── feature_cubit.dart
│   │   │   └── feature_state.dart
│   │   ├── pages/                # Screen widgets
│   │   │   └── feature_page.dart
│   │   └── widgets/              # Reusable UI components
│   │       └── feature_widget.dart
│   ├── di.dart                   # Feature dependency injection
│   └── env.dart                  # Feature environment variables

Layer Responsibilities

Domain Layer

  • Entities: Core business objects with business logic
  • Repositories: Abstract interfaces defining data contracts
  • Use Cases: Business logic operations (if needed for complex features)

Data Layer

  • Models: Data transfer objects with JSON serialization
  • Repositories: Concrete implementations of domain repositories
  • Data Sources: External data access (API, local storage)

Presentation Layer

  • Cubit/Bloc: State management using the BLoC pattern
  • Pages: Full screen widgets with routing
  • Widgets: Reusable UI components

Key Architectural Patterns

State Management

  • BLoC/Cubit: Used for state management across the application
  • Freezed: Immutable state classes with code generation
  • State Structure: Consistent state pattern with loading, data, and error states

Dependency Injection

  • GetIt: Service locator pattern for dependency injection
  • Feature DI: Each feature manages its own dependencies
  • Global DI: App-level services and configurations
  • GoRouter: Declarative routing with type-safe navigation
  • Page Structure: Each page defines static name and path constants

Error Handling

  • Failure Classes: Structured error handling with Freezed
  • Result Pattern: Success/failure return types for operations

Internationalization

  • ARB Files: Translation files for multiple languages
  • Generated Localizations: Type-safe localization with flutter_localizations

Code Generation

The project uses several code generation tools:

  • Freezed: Immutable classes and unions
  • JSON Annotation: JSON serialization/deserialization
  • Flutter Gen L10n: Localization code generation

Development Guidelines

State Management Pattern

dart
part of 'feature_cubit.dart';

@freezed
/// State for feature
abstract class FeatureState with _$FeatureState {
  /// Constructor for FeatureState
  const factory FeatureState({
    required Feature feature,
    required bool isLoading,
    Failure? failure,
  }) = _FeatureState;

  /// Initial state for FeatureState
  factory FeatureState.initial() => _FeatureState(
    feature: Feature.empty(),
    isLoading: false,
  );
}

Page Structure

dart
/// Name of the page
static const name = 'FeaturePage';

/// Path of the page
static const path = '/feature';

Context Usage

  • Use BlocProvider.of<Bloc>(context) instead of context.read<Bloc>()
  • Use GoRouter.of(context).go() instead of context.go()

Documentation

  • All public members must have /// documentation comments
  • Interactive widgets must include tooltips
  • Localize all user-facing strings

Build and Deployment

  • Flutter Analyze: Code quality checks
  • Bloc Lint: BLoC pattern compliance
  • Code Generation: Run before builds
  • Multi-platform: Support for iOS, Android, Web, Desktop

This architecture promotes:

  • Separation of Concerns: Clear layer boundaries
  • Testability: Mockable dependencies and isolated logic
  • Maintainability: Feature-based organization
  • Scalability: Easy to add new features
  • Code Reusability: Shared core components