Flutter
When your agent starts coding, you gotta let it cook
npx -y skills add ndisisnd/cook --skill flutterAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 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.
What its author says it does
Copied from the file, not written here
Universal Flutter coding standards. Use when writing or reviewing any Flutter/Dart UI code — widgets, state management, navigation, architecture, performance, or testing.
SKILL.md
8.6 KB, as published. Nobody here has run it
Flutter Standards
P0 — Design System Enforcement (CRITICAL)
Zero tolerance for hardcoded design values.
Before any UI work, identify the project's Theme Archetype by checking main.dart:
- Theme-Driven:
VThemeData(...).toThemeData()→ useTheme.of(context).textTheme - Token-Driven: Use static tokens (
VTypography.*) only when no global theme bridge exists or when defining the theme itself
Rules:
- Colors: Use tokens (
VColors.*,AppColors.*). NeverColor(0xFF...)orColors.red. - Spacing: Use tokens (
VSpacing.*). Never magic numbers like16or24. - Typography: Prefer
Theme.of(context).textTheme.*for adaptive UI. UseVTypography.*only for theme definitions. Never inlineTextStyle. - Borders: Use tokens (
VBorders.*). Never rawBorderRadius.circular(n). - Components: Use DLS widgets (
VButton) over raw Material widgets (ElevatedButton) when available.
Detail → refs/design-system.md
P0 — Error Handling (CRITICAL)
- Repositories return
Either<Failure, T>— no exceptions propagate to UI or BLoC. - Catch in Infrastructure only — convert
DioException/ external errors to typedLeft(Failure). - Fold in BLoC —
.fold(failure, success)to emit states. No try/catch in BLoC. - Typed failures —
@freezedunion failures (e.g.,UnauthorizedFailure). NeverLeft('string'). - Crashlytics routing — all
catchblocks route viaAppLogger.error(...)for observability. on Type catch— never barecatchwithouton.
Detail → refs/error-handling.md
P1 — Widgets (OPERATIONAL)
- State: Use
StatelessWidgetby default.StatefulWidgetonly for local state/controllers. - Composition: Extract UI into small, atomic
constwidgets. - Theming: Use
Theme.of(context). No hardcoded colors. - Layout: Use
Flex+Gap/SizedBox. - Widget Keys: All interactive elements must use keys from
widget_keys.dart. - File Size: If a UI file exceeds ~80 lines, extract sub-widgets into private classes.
- Specialized:
SelectionArea: For multi-widget text selection.InteractiveViewer: For zoom/pan.ListWheelScrollView: For pickers.IntrinsicWidth/Height: Avoid unless strictly required; for overlays preferStack + FractionallySizedBox.
- Large Lists: Always use
ListView.builder.
class AppButton extends StatelessWidget {
final String label;
final VoidCallback onPressed;
const AppButton({super.key, required this.label, required this.onPressed});
@override
Widget build(BuildContext context) =>
ElevatedButton(onPressed: onPressed, child: Text(label));
}
P1 — Idiomatic Flutter (OPERATIONAL)
- Async Gaps: Check
if (context.mounted)before usingBuildContextafterawait. - Composition: Extract complex UI into small widgets. Avoid deep nesting or large helper methods.
- Spacing:
- Prefer
spacingparameter onRow/Column(Flutter 3.10+) over inserting gaps between children. - Fallback: Use
Gap(n)orSizedBoxonly whenspacingcannot express the layout. - Empty UI: Use
const SizedBox.shrink(). - Simple gaps: Prefer
Gap(n)orSizedBoxoverPadding.
- Prefer
- Container: Use
ColoredBox/Padding/DecoratedBoxinstead ofContainerwhere possible. - Themes: Use extensions for
Theme.of(context)access. - No
_buildXxx()helpers: Extract toconst StatelessWidgetfor proper rebuild control.
P1 — Performance (OPERATIONAL)
- Rebuilds: Use
constwidgets andbuildWhen/selectfor granular updates. - Lists: Always use
ListView.builderfor item recycling. - Heavy Tasks: Use
compute()orIsolatesfor parsing/logic. - Repaints: Use
RepaintBoundaryfor complex animations. Debug withdebugRepaintRainbowEnabled. - Images: Use
CachedNetworkImage+memCacheWidth. UseprecachePicturefor SVGs. Always setmaxWidth/maxHeight. - Keys: Provide
ValueKeyfor list items and stable IDs. - Resource Cleanup: Dispose controllers/streams in
dispose(). - Pagination: Default to 20 items per page for network lists.
- Build Purity: Keep
build()free of heavy work; move logic to BLoC/Application.
BlocBuilder<UserBloc, UserState>(
buildWhen: (p, c) => p.id != c.id,
builder: (context, state) => Text(state.name),
)
Anti-Patterns
- No hardcoded colors/spacing:
Color(0xFF...),Colors.red,SizedBox(height: 10)are forbidden. - No inline
TextStyle: Usetheme.textTheme.*or design tokens. - No setState for server state: Server or shared state belongs in BLoC.
- No widget file over 80 lines without extraction.
- No inline Key strings: All keys must be constants defined in
widget_keys.dart. - No
_buildXxx()helper methods: Extract toconst StatelessWidgetprivate class. - No manual widget repetition: When 3+ sibling widgets differ only in data, map over a list.
- No BuildContext after await without mounted check.
- No root
setState(): UseBlocBuilderwithbuildWhenorcontext.select(). - No heavy work in
build(): Move sorting/filtering/heavy logic to BLoC orcompute(). - No non-
constleaf nodes: Applyconstto all static widgets. - No large
Columnlists: UseListView.builder. - No try/catch in BLoC: BLoC receives
Eitherand folds. - No plain string failures: Define typed
@freezedFailure subclasses. - No silent catch blocks: Always log and propagate.
- No direct controller access in widget: Use BLoC or Signals to decouple UI from state.
References
Load only what the current task requires:
- state-management — BLoC/Cubit, Riverpod, or GetX state; files matching
**_bloc.dart,**_cubit.dart,**_provider.dart,**_notifier.dart,**_controller.dart; keywords: Bloc, Cubit, Riverpod, GetX, Obx, AsyncValue, ref.watch - navigation — routing with go_router, auto_route, or GetX; files matching
**/*router*.dart,**/app_pages.dart,**/main.dart; keywords: GoRouter, AutoRoute, GetPage, Navigator, deep link, redirect - architecture — feature-based or layer-based clean architecture; files under
lib/features/**,lib/domain/**,lib/infrastructure/**,lib/application/**; keywords: feature, domain, infrastructure, DTO, mapper, Either - networking — Dio/Retrofit HTTP clients and interceptors; files under
**/data_sources/**,**/api/**; keywords: Dio, Retrofit, RestClient, Interceptor, token refresh - error-handling — Either/Failure detail and API error mapping; files under
lib/domain/**,lib/infrastructure/**; keywords: Either, fold, Left, Right, Failure, dartz - dependency-injection — get_it + injectable setup; files matching
**/injection.dart,**/locator.dart; keywords: GetIt, injectable, singleton, module - design-system — DLS token usage, modular and monolithic patterns; files under
**/theme/**,**/*_theme.dart,**/*_colors.dart; keywords: ThemeData, ColorScheme, AppColors, design token - localization — easy_localization with CSV/JSON; files under
**/translations/*.json,**/langs/*.csv; keywords: localization, tr(), easy_localization - notifications — FCM + flutter_local_notifications; files matching
**/*notification*.dart; keywords: FCM, FirebaseMessaging, push - security — OWASP Mobile, secure storage, pinning, obfuscation; files under
lib/infrastructure/**,pubspec.yaml; keywords: secure_storage, pinning, jailbreak, OWASP, PII - concurrency — isolates and compute() for heavy tasks; files matching
**/*isolate*.dart,**/*worker*.dart; keywords: Isolate, compute, ReceivePort, background - cicd — GitHub Actions and Fastlane pipelines; files under
.github/workflows/**.yml,fastlane/**; keywords: ci, cd, pipeline, deploy, workflow - testing — unit, widget, integration, robot pattern, mocking, bloc tests, widget keys; files under
**/test/**.dart,**/integration_test/**.dart,**/robots/**.dart; keywords: test, patrol, robot, blocTest, mocktail, WidgetKeys