From flutter-skills
Architects a Flutter application using the recommended layered approach (UI, Logic, Data). Use when structuring a new project or refactoring for scalability.
How this skill is triggered — by the user, by Claude, or both
Slash command
/flutter-skills:flutter-architecting-appsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
- [Core Architectural Principles](#core-architectural-principles)
Design Flutter applications to scale by strictly adhering to the following principles:
Separate the application into 2 to 3 distinct layers depending on complexity. Restrict communication so that a layer only interacts with the layer directly adjacent to it.
Follow this sequential workflow when adding a new feature to the application.
Task Progress:
// 1. Service (Stateless API Wrapper)
class UserApiService {
final HttpClient _client;
UserApiService(this._client);
Future<Map<String, dynamic>> fetchUserRaw(String userId) async {
final response = await _client.get('/users/$userId');
return response.data;
}
}
// 2. Domain Model (Immutable)
class User {
final String id;
final String name;
const User({required this.id, required this.name});
}
// 3. Repository (SSOT & Data Transformer)
class UserRepository {
final UserApiService _apiService;
User? _cachedUser;
UserRepository(this._apiService);
Future<User> getUser(String userId) async {
if (_cachedUser != null && _cachedUser!.id == userId) {
return _cachedUser!;
}
final rawData = await _apiService.fetchUserRaw(userId);
final user = User(id: rawData['id'], name: rawData['name']);
_cachedUser = user; // Cache data
return user;
}
}
// 4. ViewModel (State Management)
class UserViewModel extends ChangeNotifier {
final UserRepository _userRepository;
User? user;
bool isLoading = false;
String? error;
UserViewModel(this._userRepository);
Future<void> loadUser(String userId) async {
isLoading = true;
error = null;
notifyListeners();
try {
user = await _userRepository.getUser(userId);
} catch (e) {
error = e.toString();
} finally {
isLoading = false;
notifyListeners();
}
}
}
// 5. View (Lean UI)
class UserProfileView extends StatelessWidget {
final UserViewModel viewModel;
const UserProfileView({Key? key, required this.viewModel}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListenableBuilder(
listenable: viewModel,
builder: (context, child) {
if (viewModel.isLoading) return const CircularProgressIndicator();
if (viewModel.error != null) return Text('Error: ${viewModel.error}');
if (viewModel.user == null) return const Text('No user data.');
return Text('Hello, ${viewModel.user!.name}');
},
);
}
}
npx claudepluginhub gsmlg-dev/code-agent --plugin flutter-skillsGuides structuring Flutter apps as four-layer monorepos (Data, Repository, Business Logic, Presentation) with strict unidirectional dependencies and path-based local packages.
Provides expert Flutter/Dart patterns for cross-platform mobile apps including feature-first project structure, const widget best practices, and Riverpod/Bloc state management.
Flutter patterns — widget architecture, state management, Impeller renderer, platform-adaptive design