Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when creating a feature, designing folder structure, adding repositories/services/view models, wiring dependency injection, or deciding which layer owns logic.
.claude/skills/evanca-architecture-feature-first/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 61% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 27% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 46% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 46% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 59% | 0% |
This skill defines how to design, structure, and implement Flutter applications using the recommended layered architecture with feature-first file organization.
It is state management agnostic: the business logic holder in the UI layer may be named ViewModel, Controller, Cubit, Bloc, Provider, or Notifier — depending on the chosen state management approach. The architectural rules apply equally to all of them.
Use this skill when:
Separate every app into a UI Layer and a Data Layer. Add a Logic (Domain) Layer between them only for complex apps.
┌──────────────────────────────────────────────────────────────┐
│ UI Layer │ Views + business logic holders │
│ │ (ViewModel / Cubit / Controller / Provider) │
├──────────────────────────────────────────────────────────────┤
│ Logic Layer │ Use Cases / Interactors (optional) │
├──────────────────────────────────────────────────────────────┤
│ Data Layer │ Repositories + Services │
└──────────────────────────────────────────────────────────────┘Rules:
Organize code by feature, not by type. Group all layers belonging to one feature together in a single directory.
lib/
├── app.dart
├── main.dart
├── core/ # Shared utilities, theme, DI setup
│ ├── di/
│ │ └── service_locator.dart
│ ├── theme/
│ │ └── app_theme.dart
│ └── network/
│ └── api_client.dart
├── features/
│ ├── auth/
│ │ ├── data/
│ │ │ ├── auth_repository.dart
│ │ │ └── auth_api_service.dart
│ │ ├── domain/ # Optional — only for complex logic
│ │ │ └── login_usecase.dart
│ │ └── ui/
│ │ ├── auth_viewmodel.dart
│ │ ├── login_screen.dart
│ │ └── widgets/
│ │ └── login_form.dart
│ └── profile/
│ ├── data/
│ │ ├── profile_repository.dart
│ │ └── profile_api_service.dart
│ └── ui/
│ ├── profile_viewmodel.dart
│ └── profile_screen.dart
└── shared/ # Shared widgets, models, extensions
├── models/
│ └── user.dart
└── widgets/
└── loading_indicator.dartEach feature directory contains the files needed for that feature, named according to the chosen state management approach:
| Approach | Business logic holder file | |---|---| | MVVM / ChangeNotifier | *_viewmodel.dart / *_controller.dart | | BLoC | *_cubit.dart / *_bloc.dart | | Provider / Riverpod | *_provider.dart / *_notifier.dart |
widgets/ subdirectory.StatelessWidget when possible; keep build methods simple.dartclass AuthViewModel extends ChangeNotifier { final AuthRepository _authRepo; AuthViewModel(this._authRepo); bool _isLoading = false; bool get isLoading => _isLoading; String? _error; String? get error => _error; Future<bool> login(String email, String password) async { _isLoading = true; _error = null; notifyListeners(); try { await _authRepo.login(email, password); return true; } catch (e) { _error = e.toString(); return false; } finally { _isLoading = false; notifyListeners(); } } }
Introduce use cases/interactors only when:
Do not add a domain layer for simple CRUD apps.
Use dependency injection to provide components with their dependencies, enabling testability and flexibility.
dart// In service_locator.dart — register dependencies at startup void setupDependencies() { final apiClient = ApiClient(); // Services final authService = AuthApiService(apiClient); final profileService = ProfileApiService(apiClient); // Repositories final authRepo = AuthRepository(authService); final profileRepo = ProfileRepository(profileService); // Register with your DI framework (get_it, provider, riverpod, etc.) getIt.registerSingleton<AuthRepository>(authRepo); getIt.registerSingleton<ProfileRepository>(profileRepo); }
features/<name>/ directory with data/, ui/, and optionally domain/ subdirectories.data/<name>_api_service.dart.data/<name>_repository.dart.ui/<name>_viewmodel.dart.ui/<name>_screen.dart.Other measured skills in the registry, with their headline benchmark lift.