Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.
.claude/skills/microck-flutter-development/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 27% | 0% |
| case-18 | ✗→✓ | ▲ Improved | 197% | 0% |
| case-20 | ✗→✓ | ▲ Improved | 97% | 0% |
| case-21 | ✗→✓ | ▲ Improved | 22% | 0% |
| case-14 | ✓→✓ | = Same ✓ | 77% | 0% |
Create high-performance, visually stunning mobile applications using Flutter with Dart language. Master widget composition, state management patterns, navigation, and API integration.
dart// pubspec.yaml name: my_flutter_app version: 1.0.0 dependencies: flutter: sdk: flutter provider: ^6.0.0 http: ^1.1.0 go_router: ^12.0.0 // main.dart with GoRouter navigation import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp.router( title: 'Flutter App', theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true), routerConfig: _router, ); } } final GoRouter _router = GoRouter( routes: <RouteBase>[ GoRoute( path: '/', builder: (context, state) => const HomeScreen(), routes: [ GoRoute( path: 'details/:id', builder: (context, state) => DetailsScreen( itemId: state.pathParameters['id']! ), ), ], ), GoRoute( path: '/profile', builder: (context, state) => const ProfileScreen(), ), ], );
dartimport 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; class User { final String id; final String name; final String email; User({required this.id, required this.name, required this.email}); factory User.fromJson(Map<String, dynamic> json) { return User( id: json['id'], name: json['name'], email: json['email'], ); } } class UserProvider extends ChangeNotifier { User? _user; bool _isLoading = false; String? _error; User? get user => _user; bool get isLoading => _isLoading; String? get error => _error; Future<void> fetchUser(String userId) async { _isLoading = true; _error = null; notifyListeners(); try { final response = await http.get( Uri.parse('https://api.example.com/users/$userId'), headers: {'Content-Type': 'application/json'}, ); if (response.statusCode == 200) { _user = User.fromJson(jsonDecode(response.body)); } else { _error = 'Failed to fetch user'; } } catch (e) { _error = 'Error: ${e.toString()}'; } finally { _isLoading = false; notifyListeners(); } } void logout() { _user = null; notifyListeners(); } } class ItemsProvider extends ChangeNotifier { List<Map<String, dynamic>> _items = []; List<Map<String, dynamic>> get items => _items; Future<void> fetchItems() async { try { final response = await http.get( Uri.parse('https://api.example.com/items'), ); if (response.statusCode == 200) { _items = List<Map<String, dynamic>>.from( jsonDecode(response.body) as List ); notifyListeners(); } } catch (e) { print('Error fetching items: $e'); } } }
dartclass HomeScreen extends StatefulWidget { const HomeScreen({Key? key}) : super(key: key); @override State<HomeScreen> createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> { @override void initState() { super.initState(); Future.microtask(() { Provider.of<ItemsProvider>(context, listen: false).fetchItems(); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Home Feed')), body: Consumer<ItemsProvider>( builder: (context, itemsProvider, child) { if (itemsProvider.items.isEmpty) { return const Center(child: Text('No items found')); } return ListView.builder( itemCount: itemsProvider.items.length, itemBuilder: (context, index) { final item = itemsProvider.items[index]; return ItemCard(item: item); }, ); }, ), ); } } class ItemCard extends StatelessWidget { final Map<String, dynamic> item; const ItemCard({required this.item, Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Card( margin: const EdgeInsets.all(8), child: ListTile( title: Text(item['title'] ?? 'Untitled'), subtitle: Text(item['description'] ?? ''), trailing: const Icon(Icons.arrow_forward), onTap: () => context.go('/details/${item['id']}'), ), ); } } class DetailsScreen extends StatelessWidget { final String itemId; const DetailsScreen({required this.itemId, Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Details')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Item ID: $itemId', style: const TextStyle(fontSize: 18)), const SizedBox(height: 16), ElevatedButton( onPressed: () => context.pop(), child: const Text('Go Back'), ), ], ), ), ); } } class ProfileScreen extends StatelessWidget { const ProfileScreen({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Profile')), body: Consumer<UserProvider>( builder: (context, userProvider, child) { if (userProvider.isLoading) { return const Center(child: CircularProgressIndicator()); } if (userProvider.error != null) { return Center(child: Text('Error: ${userProvider.error}')); } final user = userProvider.user; if (user == null) { return const Center(child: Text('No user data')); } return Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Name: ${user.name}', style: const TextStyle(fontSize: 18)), Text('Email: ${user.email}', style: const TextStyle(fontSize: 16)), const SizedBox(height: 16), ElevatedButton( onPressed: () => userProvider.logout(), child: const Text('Logout'), ), ], ), ); }, ), ); } }
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-14 | pass→pass | 12,783 | 9,875 | -23% | 1 | 1 | 0% | 2,138 | 3,781 | +77% | 0 | 0 | — |
case-09 | fail→fail | 10,783 | 7,857 | -27% | 1 | 1 | 0% | 1,862 | 3,451 | +85% | 0 | 0 | — |
case-01 | fail→fail | 10,939 | 9,703 | -11% | 1 | 1 | 0% | 2,279 | 4,251 | +87% | 0 | 0 | — |
case-02 | fail→fail | 13,505 | 10,510 | -22% | 1 | 1 | 0% | 2,954 | 4,325 | +46% | 0 | 0 | — |
case-03 | fail→pass | 14,937 | 9,782 | -35% | 1 | 1 | 0% | 3,230 | 4,089 | +27% | 0 | 0 | — |
case-04 | pass→pass | 15,900 | 13,622 | -14% | 1 | 1 | 0% | 3,234 | 4,929 | +52% | 0 | 0 | — |
case-05 | pass→pass | 13,536 | 12,414 | -8% | 1 | 1 | 0% | 2,506 | 4,317 | +72% | 0 | 0 | — |
case-06 | pass→pass | 12,933 | 12,072 | -7% | 1 | 1 | 0% | 2,379 | 4,149 | +74% | 0 | 0 | — |
case-07 | pass→pass | 14,435 | 12,321 | -15% | 1 | 1 | 0% | 2,349 | 4,088 | +74% | 0 | 0 | — |
case-08 | pass→pass | 8,172 | 5,675 | -31% | 1 | 1 | 0% | 1,370 | 2,987 | +118% | 0 | 0 | — |
case-10 | pass→pass | 9,014 | 5,262 | -42% | 1 | 1 | 0% | 1,574 | 2,877 | +83% | 0 | 0 | — |
case-11 | pass→pass | 5,365 | 2,930 | -45% | 1 | 1 | 0% | 819 | 2,503 | +206% | 0 | 0 | — |
case-12 | pass→pass | 10,221 | 9,562 | -6% | 1 | 1 | 0% | 1,778 | 3,814 | +115% | 0 | 0 | — |
case-13 | pass→pass | 6,319 | 3,371 | -47% | 1 | 1 | 0% | 1,113 | 2,609 | +134% | 0 | 0 | — |
case-15 | fail→fail | 15,266 | 15,394 | +1% | 1 | 1 | 0% | 2,601 | 4,905 | +89% | 0 | 0 | — |
case-16 | pass→pass | 4,196 | 4,146 | -1% | 1 | 1 | 0% | 788 | 2,717 | +245% | 0 | 0 | — |
case-17 | pass→pass | 5,841 | 3,424 | -41% | 1 | 1 | 0% | 1,007 | 2,623 | +160% | 0 | 0 | — |
case-18 | fail→pass | 5,592 | 4,261 | -24% | 1 | 1 | 0% | 916 | 2,724 | +197% | 0 | 0 | — |
case-19 | pass→pass | 9,144 | 7,250 | -21% | 1 | 1 | 0% | 1,617 | 3,337 | +106% | 0 | 0 | — |
case-20 | fail→pass | 8,245 | 3,985 | -52% | 1 | 1 | 0% | 1,419 | 2,792 | +97% | 0 | 0 | — |
case-21 | fail→pass | 13,732 | 5,132 | -63% | 1 | 1 | 0% | 2,350 | 2,860 | +22% | 0 | 0 | — |
case-22 | pass→pass | 13,646 | 14,097 | +3% | 1 | 1 | 0% | 2,360 | 4,505 | +91% | 0 | 0 | — |
case-23 | pass→pass | 10,722 | 10,379 | -3% | 1 | 1 | 0% | 1,905 | 3,962 | +108% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +17 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.