aeo-optimization
AI Engine Optimization - semantic triples, page templates, content clusters for AI citations
Flutter development with Riverpod state management, Freezed, go_router, and mocktail testing
$ npx -y skills add alinaqi/maggy --skill flutter --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/flutterContext preview
The summary Claude sees to decide when to auto-load this skill.
Flutter development with Riverpod state management, Freezed, go_router, and mocktail testing
name: flutter description: Flutter development with Riverpod state management, Freezed, go_router, and mocktail testing when-to-use: When working on Flutter/Dart code user-invocable: false paths: ["**/*.dart", "pubspec.yaml", "lib/**", "test/**"] effort: medium
---
project/ ├── lib/ │ ├── core/ # Core utilities │ │ ├── constants/ # App constants │ │ ├── extensions/ # Dart extensions │ │ ├── router/ # go_router configuration │ │ │ └── app_router.dart │ │ └── theme/ # App theme │ │ └── app_theme.dart │ ├── data/ # Data layer │ │ ├── models/ # Freezed data models │ │ ├── repositories/ # Repository implementations │ │ └── services/ # API services │ ├── domain/ # Domain layer │ │ ├── entities/ # Business entities │ │ └── repositories/ # Repository interfaces │ ├── presentation/ # UI layer │ │ ├── common/ # Shared widgets │ │ ├── features/ # Feature modules │ │ │ └── feature_name/ │ │ │ ├── providers/ # Riverpod providers │ │ │ ├── widgets/ # Feature-specific widgets │ │ │ └── feature_screen.dart │ │ └── providers/ # Global providers │ ├── main.dart │ └── app.dart ├── test/ │ ├── unit/ # Unit tests │ ├── widget/ # Widget tests │ └── integration/ # Integration tests ├── pubspec.yaml ├── analysis_options.yaml └── CLAUDE.md
---
// Simple value provider
final appNameProvider = Provider<String>((ref) => 'My App');
// StateProvider for simple mutable state
final counterProvider = StateProvider<int>((ref) => 0);
// NotifierProvider for complex state logic
final userProvider = NotifierProvider<UserNotifier, User?>(() => UserNotifier());
// AsyncNotifierProvider for async operations
final usersProvider = AsyncNotifierProvider<UsersNotifier, List<User>>(
() => UsersNotifier(),
);
// FutureProvider for simple async data
final configProvider = FutureProvider<Config>((ref) async {
return await ref.watch(configServiceProvider).loadConfig();
});
// StreamProvider for real-time data
final messagesProvider = StreamProvider<List<Message>>((ref) {
return ref.watch(messageServiceProvider).watchMessages();
});
// Family providers for parameterized data
final userByIdProvider = FutureProvider.family<User, String>((ref, userId) async {
return await ref.watch(userRepositoryProvider).getUser(userId);
});@riverpod
class Users extends _$Users {
@override
Future<List<User>> build() async {
return await _fetchUsers();
}
Future<List<User>> _fetchUsers() async {
final repository = ref.read(userRepositoryProvider);
return await repository.getUsers();
}
Future<void> refresh() async {
state = const AsyncLoading();
state = await AsyncValue.guard(() => _fetchUsers());
}
Future<void> addUser(User user) async {
final repository = ref.read(userRepositoryProvider);
await repository.addUser(user);
ref.invalidateSelf();
}
}class UsersScreen extends ConsumerWidget {
const UsersScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final usersAsync = ref.watch(usersProvider);
return usersAsync.when(
data: (users) => UsersList(users: users),
loading: () => const Center(child: CircularProgressIndicator()),
error: (error, stack) => ErrorDisplay(
error: error,
onRetry: () => ref.invalidate(usersProvider),
),
);
}
}
// Pattern matching alternative
Widget build(BuildContext context, WidgetRef ref) {
final usersAsync = ref.watch(usersProvider);
return switch (usersAsync) {
AsyncData(:final value) => UsersList(users: value),
AsyncLoading() => const LoadingIndicator(),
AsyncError(:final error) => ErrorDisplay(error: error),
};
}// watch - rebuilds when provider changes
final users = ref.watch(usersProvider);
// read - one-time read, no rebuild
void onButtonPressed() {
ref.read(counterProvider.notifier).state++;
}
// listen - react to changes without rebuild
ref.listen(authProvider, (previous, next) {
if (next == null) {
context.go('/login');
}
});
// invalidate - force refresh
ref.invalidate(usersProvider);
// keepAlive - prevent auto-dispose
final link = ref.keepAlive();
// Later: link.close() to allow disposal---
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
class User with _$User {
const factory User({
required String id,
required String name,
required String email,
@Default(false) bool isActive,
DateTime? createdAt,
}) = _User;
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}
// Union types for states
@freezed
sealed class AuthState with _$AuthState {
const factory AuthState.initial() = _Initial;
const factory AuthState.loading() = _Loading;
const factory AuthState.authenticated(User user) = _Authenticated;
const factory AuthState.unauthenticated() = _Unauthenticated;
const factory AuthState.error(String message) = _Error;
}Widget build(BuildContext context, WidgetRef ref) {
final authState = ref.watch(authProvider);
return authState.when(
initial: () => const SplashScreen(),
loading: () => const LoadingScreen(),
authenticated: (user) => HomeScreen(user: user),
unauthenticated: () =>Turn Claude Code into a self-reviewing, test-enforced engineering system that remembers context across sessions — then route work across 13 models from a single dashboard.
Repo: alinaqi/maggy
AI Engine Optimization - semantic triples, page templates, content clusters for AI citations
Claude Code Agent Teams - default team-based development with strict TDD pipeline enforcement
Build AI agents with Pydantic AI (Python) and Claude SDK (Node.js)
Latest AI models reference - Claude, OpenAI, Gemini, Eleven Labs, Replicate
Android Kotlin development with Coroutines, Jetpack Compose, Hilt, and MockK testing