Flutter clean architecture
Skill Mkhira/flutter-clean-architecture/skills/flutter-clean-architecture
Use this skill when creating a new Flutter project, implementing Flutter or Dart features, writing code in an existing Flutter project, refactoring Flutter/Dart code, or reviewing Flutter code. Trigger whenever the user asks to create a Flutter project/app by name, or when the current workspace is a Flutter project and the task involves implementation, coding, API integration, models, Bloc/Cubit, UI, theming, localization, dependency injection, networking, tests, or code review — even if the user does not explicitly say "clean architecture". For new project creation, ask the user for the directory and project name before running flutter create.From its SKILL.md
npx -y skills add Mkhira/flutter-clean-architecture --skill flutter-clean-architectureAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
11.2 KB, ~2.6k tokens by cl100k_base, as published. Nobody here has run it
Flutter Clean Architecture
Purpose
This skill enforces a practical, opinionated, feature-first Flutter Clean
Architecture (presentation / domain / data per feature) so the agent behaves like
a careful senior engineer: UI renders, state coordinates, domain holds
application logic, data talks to the outside world, and infrastructure errors
never leak into widgets. The standardized stack — Bloc/Cubit · Dio+Retrofit ·
JsonSerializable · GetIt · Envied+Flavorizr · Easy Localization (+
flutter_localizations) · centralized theme · responsive UI · testing — and its
exact package sets live in package-stack.md and the per-area references; load
those, don't restate them here.
Mode Detection
There are two modes. Detect which one applies before doing anything else.
New Project Mode
Trigger when the user asks to create a Flutter project/app (e.g. "create flutter project my_app").
Rules:
-
If the user does not give a project name, ask for one.
-
If the user gives a name but not the directory path, ask:
Where should I create the project directory? -
Optionally confirm the organization identifier (
--org, e.g.com.example), because it determines the AndroidapplicationIdand iOSbundleIdlater used by flavors. Default tocom.exampleonly if the user does not care.
Scaffold scope: Full vs Lean
A from-scratch Full scaffold is large (≈100–140k tokens): products + settings demo features, multi-flavor Envied + Flutter Flavorizr, full test suite. That is the right default when the user wants a production-shaped foundation — but it over-delivers (and over-spends) for a quick start.
- Full mode (default): the complete scaffold in
references/project-creation.md. - Lean mode: trigger when the user says "minimal", "lean", "quick start",
"barebones", "no demo feature/flavors", or similar. Scaffold only:
core/(DI, theme, localization, router, network, error) +app/+ a single minimal home screen (e.g. thecounterCubit frombloc-cubit.md, or an emptyHomePage). Skip the products & settings demo features, skip flavorizr/multi-flavor (use a singlemain.dart+ one.envor--dart-define), and add only the packages that minimal set needs. Still set upanalysis_options.yaml, localization assets, DI, and theme.
If the scope is ambiguous for a from-scratch project, ask once (one line: "Full scaffold with demo feature + flavors, or a lean minimal start?") rather than defaulting to the heavy build silently.
State-management stack
After name/directory/org, ask once:
Which state management stack?
1. Bloc/Cubit (default) 2. Riverpod 3. Provider 4. GetX 5. MobX
If the user does not choose (or the run is non-interactive), default to
Bloc/Cubit. The chosen stack only changes the presentation layer + its DI
wiring — domain and data are identical for every stack. The stack adds its
packages on top of the base set; see the per-stack sets in package-stack.md.
Load only that stack's reference (below) — e.g. a Riverpod project reads
references/riverpod.md instead of references/bloc-cubit.md.
Do not run flutter create until the name and directory are known. If the user
gives both name and directory, proceed.
Then follow references/project-creation.md (and apply Lean trimming above when
Lean mode is selected). For the Full scaffold, prefer the fast path —
scripts/scaffold_default_features.sh . drops the validated, analyze-clean
core/app/products/settings code (substituting the package name) instead of
hand-emitting ~100k tokens; then scripts/flavorize.sh for flavors. See the
"Fast path" note at the top of project-creation.md.
Existing Project Mode
Trigger when:
pubspec.yamlexists and containsflutter:, orpubspec.yamldepends on the Flutter SDK, or- the user mentions Flutter/Dart implementation, coding, review, refactor, Bloc/Cubit, widget, route, API, model, repository, theme, or feature.
Inspect before coding:
pubspec.yaml
analysis_options.yaml
lib/
test/
existing feature folders
existing routing setup
existing DI setup
existing state management
existing theme setup
existing codegen/build.yaml
Detect the state-management stack first. Before adding a feature or layer,
run scripts/detect_stack.sh (prints bloc|riverpod|provider|getx|mobx|unknown)
and generate in that stack — load its reference (below) instead of
bloc-cubit.md. If unknown, ask. Never impose Bloc on a non-Bloc project.
Follow existing project conventions unless the user explicitly asks to migrate or to establish the architecture. A consistent existing convention beats this skill's defaults.
Progressive Reference Loading
Read only what the task needs.
- Always read
references/architecture.md. - New projects: also read
references/project-creation.md,references/package-stack.md,references/env-and-flavors.md,references/localization.md,references/theme.md,references/dependency-injection.md,references/routing.md, andreferences/testing.md. - Feature implementation: read
references/feature-generation.md, the active stack's reference (below), and the relevant domain files. Scaffold the skeleton withscripts/new_feature.sh <ui|api|form> <name>first (saves output tokens), then fill the logic. For a plural feature name, add--item <singular>so the entity/model are singular (e.g.api elixirs --item elixir). Add--json <file>to infer the entity/model (incl. nested types) from a sample response instead of the single-idstub. If the API has an OpenAPI/Swagger spec, prefer--openapi <spec> --path <endpoint>: it generates exact types and the Retrofit client + Dio-backed datasource from the contract. - State management — load ONLY the active stack (it replaces
bloc-cubit.md, it does not stack on top):bloc-cubit.md(default) ·riverpod.md·provider.md·getx.md·mobx.md. Domain/data are identical regardless; only presentation + DI wiring differ. - Dio/Retrofit work: read
references/api-contracts.md,references/networking.md,references/models-and-codegen.md, andreferences/errors-and-results.md. - build_runner / codegen failures: read
references/codegen-troubleshooting.mdthe moment a generation step errors (don't blind-retry). - Auth/token work: read
references/auth-and-secure-storage.md. - UI/styling work: read
references/theme.mdandreferences/responsive-ui.md. - Assets / images / SVG / fonts: read
references/assets-and-codegen.md(flutter_gen type-safe accessors, the flutter_svg silent-failure gotcha, resolution-aware images, fonts). - Golden / integration tests: see those sections in
references/testing.md(goldens are flaky without font loading + a controlled env — use alchemist). - Forms: read
references/forms.md. - Localization: read
references/localization.md. - Connectivity: read
references/connectivity.md. - Logging: read
references/logging.md. - Review work: read
references/review-checklist.md.
Non-Negotiable Rules
- Do not invent API request/response models. Ask for JSON request/response examples unless they already exist in the repo, Swagger/OpenAPI/Postman docs, tests, or a backend contract.
- Do not expose
DioExceptionto UI. - Do not place business logic inside widgets.
- Do not add packages to an existing project unless needed.
- Do not introduce a new state management package; use Bloc/Cubit unless the existing project clearly uses another pattern.
- Do not edit generated files manually.
- Do not hardcode colors/text styles in widgets when a theme token exists; consume the theme.
- Run
dart run build_runner build --delete-conflicting-outputsonly after editing files related to.g.dart,.freezed.dart, Retrofit, Envied, JsonSerializable, or Freezed. (Newer build_runner — 2.15+ — has removed--delete-conflicting-outputsand now ignores it with a harmless warning; the flag is still safe to pass for older versions, so keep it.) - For normal UI/Cubit/repository/usecase edits, do not run build_runner unless generated-code inputs changed.
- Do not introduce a
bootstrap.dart/bootstrap()indirection. Flutter's entrypoint convention ismain()inmain.dart. Put startup directly inmain(); if multiple flavor entrypoints must share startup, factor it into a clearly named function (e.g.runApplication()) in the app composition root (app/app.dart), not abootstrapfile. - Use latest compatible package versions. Prefer
flutter pub add package_name/flutter pub add dev:package_nameso Pub resolves the latest compatible version. If exact versions are written, verify latest first. - For new project creation, always ask for project name and target directory if missing.
Validation Workflow
- Preflight with
scripts/doctor.shbefore building features or after touchingpubspec.yaml: it checks the SDK, runsflutter pub get(and points at the conflict playbook if resolution fails), and reports outdated key packages.--docsalso scans references for stale version mentions. - Run
dart format .after edits. - Run
dart fix --applyafter scaffolding a project from a template (e.g.scripts/scaffold_default_features.sh): the project's ownpackage:<name>/...imports sort to a name-dependent position, so a template authored for one name tripsdirectives_orderingunder another.dart fix --applynormalizes it. - Run
flutter analyzefor Flutter projects. - After any domain-layer edit, run
scripts/check_layers.sh— it fails if adomain/file imports Flutter/Dio/GetIt/etc. Keep the domain pure (seereferences/architecture.md). - Run relevant
flutter testwhen tests exist or behavior changed. Use the compact reporter and scope to what changed to keep output (and token cost) small:flutter test -r compact test/path/to/changed_test.dart. The default expanded reporter prints a progress line per test — several thousand tokens per run;-r compactcollapses that to a single updating line. Only run the wholetest/suite (still with-r compact) for a final pass. - Run
dart run build_runner build --delete-conflicting-outputsonly when generated-code inputs changed. - Use
scripts/validate_flutter_project.shwhen appropriate (it runs pub get, conditional build_runner, format, analyze, and tests). Its steps are quiet on success (one✓ <step>line each) and print diagnostics only on failure; during iteration scopeflutter analyzetolib/features/<feature>, fulllibonly on the final pass.
What ships with it: 91 files
345.7 KB alongside SKILL.md, 11 of them executable
assets/
- default-scaffold/analysis_options.yaml618 B
- default-scaffold/assets/lang/ar.json802 B
- default-scaffold/assets/lang/en.json666 B
- default-scaffold/env/.env.dev37 B
- default-scaffold/env/.env.prod33 B
- default-scaffold/env/.env.staging41 B
- default-scaffold/lib/app/app_bloc_observer.dart640 B
- default-scaffold/lib/app/app.dart2.5 KB
- default-scaffold/lib/core/di/injection.dart1.7 KB
- default-scaffold/lib/core/env/env.dart204 B
- default-scaffold/lib/core/env/env_dev.dart199 B
- default-scaffold/lib/core/env/env_prod.dart203 B
- default-scaffold/lib/core/env/env_staging.dart215 B
- default-scaffold/lib/core/error/error_mapper.dart823 B
- default-scaffold/lib/core/error/failures.dart790 B
- default-scaffold/lib/core/error/result.dart463 B
- default-scaffold/lib/core/network/dio_client.dart547 B
- default-scaffold/lib/core/router/app_router.dart421 B
- default-scaffold/lib/core/theme/app_colors.dart241 B
- default-scaffold/lib/core/theme/app_theme.dart638 B
- default-scaffold/lib/core/theme/app_tokens.dart1.0 KB
- default-scaffold/lib/features/products/data/api/products_api_client.dart403 B
- default-scaffold/lib/features/products/data/datasources/products_fake_remote_data_source.dart1.6 KB
- default-scaffold/lib/features/products/data/datasources/products_remote_data_source.dart785 B
- default-scaffold/lib/features/products/data/models/product_category_model.dart588 B
- default-scaffold/lib/features/products/data/models/product_model.dart908 B
- default-scaffold/lib/features/products/data/models/products_page_model.dart1.1 KB
- default-scaffold/lib/features/products/data/repositories/products_repository_impl.dart1.0 KB
- default-scaffold/lib/features/products/domain/entities/paginated_products.dart619 B
- default-scaffold/lib/features/products/domain/entities/product_category.dart251 B
- default-scaffold/lib/features/products/domain/entities/product.dart456 B
- default-scaffold/lib/features/products/domain/repositories/products_repository.dart243 B
- default-scaffold/lib/features/products/domain/usecases/get_products_use_case.dart508 B
- default-scaffold/lib/features/products/presentation/bloc/products_bloc.dart2.0 KB
- default-scaffold/lib/features/products/presentation/bloc/products_event.dart518 B
- default-scaffold/lib/features/products/presentation/bloc/products_state.dart1.0 KB
- default-scaffold/lib/features/products/presentation/pages/products_page.dart4.2 KB
- default-scaffold/lib/features/products/presentation/widgets/product_card.dart1017 B
- default-scaffold/lib/features/settings/presentation/bloc/settings_bloc.dart893 B
- default-scaffold/lib/features/settings/presentation/bloc/settings_event.dart531 B
51 more files not listed here. See all 91 in the repository.