clean_architect 0.1.6
clean_architect: ^0.1.6 copied to clipboard
A configurable CLI generator for clean architecture Flutter and Dart feature modules.
clean_architect #
A configurable Dart CLI generator for Clean Architecture Flutter/Dart projects.
clean_architect generates boring, predictable architecture files that you can edit immediately. The generator does not try to hide your app behind runtime abstractions. The flexibility lives in clean_architect.yaml: paths, layer layout, state management, network client, local storage, model style, and dependency injection style.
Install #
dart pub global activate clean_architect
After global activation you can run the executable from any folder:
clean_architect init
clean_architect create architecture
clean_architect create auth
clean_architect create feature orders
Empty Folder Usage #
Use the global executable when generating into an empty folder:
mkdir my_app
cd my_app
clean_architect create architecture
Do not use dart run clean_architect ... in an empty folder. dart run needs a local pubspec.yaml before the CLI can start. Use dart run clean_architect ... only when developing this package from its own checkout or from another Dart project that already has a pubspec.yaml.
Commands #
clean_architect init
clean_architect doctor
clean_architect create architecture
clean_architect create base
clean_architect create auth
clean_architect create feature <name>
clean_architect create usecase <name> --feature <feature>
clean_architect create repository <feature>
Examples:
clean_architect init
clean_architect create architecture
clean_architect create feature orders
clean_architect create auth
clean_architect create usecase login --feature auth
clean_architect create repository auth
clean_architect doctor
Useful flags:
clean_architect init --dry-run
clean_architect init --force
clean_architect create architecture --dry-run
clean_architect create auth --dry-run
clean_architect create auth --overwrite
clean_architect create auth --force
clean_architect create feature profile --skip-presentation
clean_architect create auth --state getx
clean_architect create auth --state none
clean_architect create auth --network dio
clean_architect create auth --network abstract
clean_architect create auth --storage secure_storage
clean_architect create auth --storage abstract
clean_architect create auth --di injectable
clean_architect create auth --dependency-injection manual
--overwrite and --force are required before existing generated files are replaced.
Configuration File #
Run:
clean_architect init
This creates clean_architect.yaml:
clean_architect:
structure: layered_packages # layered_packages or feature_first
state_management: getx # getx or none
network: dio # dio or abstract
local_storage: secure_storage # secure_storage or abstract
dependency_injection: manual # manual or injectable
use_asset_generator: true
models:
use_freezed: true
use_json_serializable: true
paths:
domain: domain/lib
data: data/lib/features
presentation: presentation/lib
di: di/lib
Configuration Reference #
| Key | Values | Default | What it controls |
|---|---|---|---|
structure |
layered_packages, feature_first |
layered_packages |
How feature paths are resolved from the configured layer paths. |
state_management |
getx, none |
getx |
Presentation controller/page style. |
network |
dio, abstract |
dio |
Remote data source style and generated data dependencies. |
local_storage |
secure_storage, abstract |
secure_storage |
Local auth credential storage style. |
dependency_injection |
manual, injectable |
manual |
Manual DI builder files or injectable/get_it setup files and annotations. |
use_asset_generator |
true, false |
true |
Whether presentation gets asset_generator_kit.yaml and the asset generator dependency. |
models.use_freezed |
true, false |
true |
Whether entities/DTOs use Freezed. |
models.use_json_serializable |
true, false |
true |
Whether DTOs include JSON serialization parts/factories. |
paths.domain |
path | domain/lib |
Domain layer feature root. |
paths.data |
path | data/lib/features |
Data layer feature root. |
paths.presentation |
path | presentation/lib |
Presentation layer root. |
paths.di |
path | di/lib |
Dependency injection layer root. |
The config parser also recognizes local_storage: shared_preferences, but the current templates only generate concrete storage code for secure_storage; use abstract when you want to wire your own storage implementation.
CLI overrides are intentionally small and only affect the current command. They do not rewrite clean_architect.yaml.
Generated Project Shape #
The default architecture is a multi-package Flutter/Dart workspace shape:
my_app/
domain/
pubspec.yaml
lib/
features/
base_feature/
entities/
repositories/
usecases/
data/
pubspec.yaml
lib/
features/
base_feature/
remote/
models/
local/
models/
repositories/
di/
pubspec.yaml
lib/
presentation/
pubspec.yaml
analysis_options.yaml
asset_generator_kit.yaml
assets/
images/
icons/
lib/
main.dart
widgets/
pages/
utils/
controllers/
constants/
Every layer gets its own pubspec.yaml:
domainis a pure Dart package for entities, repository contracts, and use cases.datais a Dart/Flutter package for DTOs, API services, local sources, mappers, and repository implementations.diis a Dart package that connectsdomainanddatadependencies.presentationis a runnable Flutter package withmain.dart, Flutter dependencies, and UI folders.
After generation, run Flutter setup inside presentation when you want a complete Flutter platform project:
cd presentation
flutter create .
flutter pub get
Run dart pub get in the other layer packages as needed.
Structure Modes #
Default Layered Packages #
clean_architect:
structure: layered_packages
paths:
domain: domain/lib
data: data/lib/features
presentation: presentation/lib
di: di/lib
clean_architect create auth creates:
domain/lib/features/auth/...
data/lib/features/auth/...
di/lib/auth_di.dart
presentation/lib/controllers/auth_controller.dart
presentation/lib/pages/login_page.dart
presentation/lib/widgets/login_view_item.dart
Custom Layer Paths #
You can point the layers to existing packages or app folders:
clean_architect:
structure: layered_packages
paths:
domain: packages/domain/lib/modules
data: packages/data/lib/modules
presentation: apps/customer_app/lib
di: packages/di/lib
Then clean_architect create feature profile creates feature files under those configured roots.
Feature First #
feature_first is available for projects that still want feature-based grouping while keeping the same layer packages:
clean_architect:
structure: feature_first
paths:
domain: domain/lib
data: data/lib/features
presentation: presentation/lib
di: di/lib
Current path resolution places domain files under domain/lib/features/<feature> and data files under data/lib/features/<feature>. Presentation files stay in shared presentation folders: pages, controllers, and widgets.
create architecture #
clean_architect create architecture
Generates the layer packages and default folders only. It does not generate auth code.
Default placeholder feature name:
domain/lib/features/base_feature
data/lib/features/base_feature
Use this when you want the clean architecture project skeleton first, then add features later.
create feature <name> #
clean_architect create feature orders
Generates a generic feature module.
Domain:
domain/lib/features/orders/entities/orders_entity.dart
domain/lib/features/orders/repositories/orders_repository.dart
domain/lib/features/orders/usecases/get_orders_list_use_case.dart
Data:
data/lib/features/orders/remote/models/orders_dto.dart
data/lib/features/orders/remote/orders_api_service.dart
data/lib/features/orders/local/models/.gitkeep
data/lib/features/orders/local/orders_local_data_source.dart
data/lib/features/orders/mappers/orders_mapper.dart
data/lib/features/orders/repositories/orders_repository_impl.dart
Presentation, unless --skip-presentation is used:
presentation/lib/controllers/orders_controller.dart
presentation/lib/pages/orders_page.dart
presentation/lib/widgets/orders_view_item.dart
The generic feature is intentionally minimal: entity, DTO, mapper, repository contract, repository implementation, list use case, local source, Retrofit API service, controller, page, and view item.
create auth #
clean_architect create auth
Generates a concrete auth starter feature.
Domain:
domain/lib/features/auth/entities/auth_token_entity.dart
domain/lib/features/auth/entities/auth_credentials_entity.dart
domain/lib/features/auth/repositories/auth_repository.dart
domain/lib/features/auth/usecases/login_use_case.dart
domain/lib/features/auth/usecases/logout_use_case.dart
domain/lib/features/auth/usecases/save_auth_credentials_use_case.dart
domain/lib/features/auth/usecases/get_auth_credentials_use_case.dart
domain/lib/features/auth/usecases/clear_auth_credentials_use_case.dart
Data:
data/lib/features/auth/remote/models/auth_token_dto.dart
data/lib/features/auth/remote/models/login_request_dto.dart
data/lib/features/auth/remote/auth_api_service.dart
data/lib/features/auth/local/models/.gitkeep
data/lib/features/auth/local/auth_local_data_source.dart
data/lib/features/auth/mappers/auth_token_mapper.dart
data/lib/features/auth/repositories/auth_repository_impl.dart
Presentation, unless --skip-presentation is used:
presentation/lib/controllers/auth_controller.dart
presentation/lib/pages/login_page.dart
presentation/lib/widgets/login_view_item.dart
The generated remote API service uses Dio + Retrofit style:
@lazySingleton
@RestApi(baseUrl: '')
abstract class AuthApiService {
@factoryMethod
factory AuthApiService(@Named("auth_dio") Dio dio) = _AuthApiService;
@POST('/authorization/token/')
Future<AuthTokenDto> login(@Body() Map<String, dynamic> body);
}
The generated auth controller uses GetIt.instance.get<LoginUseCase>(), and the GetX page registers the controller in initState with Get.put(AuthController()).
Dependency Injection Modes #
Manual #
dependency_injection: manual
Manual mode generates simple DI builder files, for example:
di/lib/auth_di.dart
di/lib/orders_di.dart
Use this when you want explicit constructors and simple dependency wiring you can edit by hand.
Injectable #
dependency_injection: injectable
Injectable mode adds injectable/get_it dependencies and generates injector entry files:
domain/lib/injector.dart
data/lib/injector.dart
di/lib/di.dart
Generated classes receive injectable annotations where supported. After generation, run build runner in the generated packages that contain injectable/freezed/json_serializable code.
Model Modes #
Freezed + JSON Serializable #
models:
use_freezed: true
use_json_serializable: true
Entities and DTOs use Freezed. DTOs also include JSON serialization parts when JSON serialization is enabled.
Typical follow-up command in generated packages:
dart run build_runner build --delete-conflicting-outputs
Plain Dart Fallback #
models:
use_freezed: false
use_json_serializable: false
Entities and DTOs are generated as simple Dart classes.
State Management #
GetX #
state_management: getx
Presentation controllers extend GetxController, pages use Get.put(...), Get.find(...), and reactive values where needed.
None #
state_management: none
Presentation files are generated without GetX page wiring. This is useful when you want to connect Bloc, Riverpod, Provider, or another state system manually.
Network #
Dio #
network: dio
Generated remote services use Dio + Retrofit imports and annotations. The data package receives the relevant dependencies.
Abstract #
network: abstract
Use this when you want the generated repositories and source boundaries but plan to implement networking yourself.
Local Storage #
Secure Storage #
local_storage: secure_storage
Auth local source uses flutter_secure_storage for credential persistence.
Abstract #
local_storage: abstract
Auth local source contains TODO methods so you can wire Hive, shared preferences, a database, encrypted storage, or another persistence mechanism yourself.
Presentation Package #
The generated presentation package includes:
presentation/lib/main.dart
presentation/lib/widgets/
presentation/lib/pages/
presentation/lib/utils/
presentation/lib/controllers/
presentation/lib/constants/
presentation/assets/images/
presentation/assets/icons/
When use_asset_generator: true, it also includes:
presentation/asset_generator_kit.yaml
and adds assetgeneratorkit to presentation/pubspec.yaml.
Safety #
By default, existing files are not overwritten.
Preview generated files:
clean_architect create auth --dry-run
Overwrite intentionally:
clean_architect create auth --overwrite
or:
clean_architect create auth --force
Doctor #
clean_architect doctor
doctor loads clean_architect.yaml, checks whether configured paths exist, and prints dependency reminders for selected options such as Dio, GetX, and secure storage.
Publishing / Development Notes #
When working on this package locally:
dart format lib test bin
dart analyze
dart test
dart pub publish --dry-run
Run dart pub publish --dry-run before publishing to verify pub.dev metadata and package contents.