Receber por email
← Voltar para o catálogo

building-flutter-apps

CRÍTICO: Invoque esta skill antes de responder a qualquer pergunta sobre Flutter ou Dart, pois ela codifica regras de arquitetura e anti-padrões específicos do projeto que substituem as melhores práticas públicas; responder sem ela produzirá código que falhará na revisão. Invoque para qualquer prompt que mencione Flutter, Dart, Riverpod, Freezed, GoRouter, Hiv.

19estrelas
Atualizado há 3 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add sgaabdu4/building-flutter-apps

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/building-flutter-apps/svg)](https://www.skillteca.com.br/skills/building-flutter-apps)
#ai

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Gate

On skill activation, emit verbatim once:

building-flutter-apps active. Pre-flight required.

Before writing any .dart code, emit verbatim:

Reading building-flutter-apps gate.

After every code change to a .dart file (or to pubspec.yaml / build.yaml / analysis_options.yaml):

  1. Run dart analyze from the package root. Block on any ERROR or WARNING.
  2. Emit the filled-in Pre-Flight checklist. T0 always. T1 / T2 only if their domain was touched.
  3. If dart analyze is not wired with flutter_skill_lints, run Setup before continuing.

Critical Rules

  1. Use dart analyze from package root, never flutter analyze and never path-scoped. Copy [references/analysis_options.yaml](references/analysis_options.yaml) to project root and wire flutter_skill_lints + riverpod_lint under plugins:. flutter analyze lib silently drops plugin diagnostics (flutter#184190).
  1. Use @riverpod / @Riverpod codegen for every provider — state, computed, repository, datasource, service, family, stream. Never manual Provider, FutureProvider, StreamProvider, StateProvider, StateNotifierProvider, NotifierProvider, AsyncNotifierProvider, ChangeNotifierProvider. Run dart run build_runner watch --delete-conflicting-outputs.
  1. Guard every await in notifiers and repositories with if (!ref.mounted) return;. Guard every await in widgets and State with if (!context.mounted) return;. Inside State, never if (mounted) — always if (!context.mounted) return;. Inside finally, use the guard form if (ref.mounted) { ... } — never if (!ref.mounted) return;.
  1. Extract widgets to public classes. No _buildXxx() helpers. No class _Foo extends StatelessWidget | StatefulWidget | ConsumerWidget | ConsumerStatefulWidget | HookWidget | HookConsumerWidget. Mark file-internal widgets @visibleForTesting. _FooState extends State<Foo> stays private (Flutter convention — exempt).
  1. Use Object? or a specific type for unknown values. dynamic only for Map<String, dynamic> JSON. Never value! — use if (value case final v?).
  1. Use AppLocalizations (gen-l10n) for every user-facing string. Never hardcode UI copy in widgets, notifiers, repositories, or datasources. In widgets, bind final l10n = context.l10n; at the top of build and use l10n.someKey; never chain context.l10n.someKey. *Strings constants only for non-user-facing IDs. For l10n config, put ARB files in arb-dir (lib/l10n by default). Generated Dart is written to ${arb-dir}/${output-localization-file} unless output-dir is set; import app_localizations.dart from that directory.
  1. Use sealed class for Freezed unions and states. Never abstract class with @freezed. Match with Dart native switch — never Freezed .when() / .map(). For VOs in /domain/values/, annotate @Freezed(map: FreezedMapOptions.none, when: FreezedWhenOptions.none) to disable codegen of those methods entirely. Lint: freezed_disable_map_when_required.
  1. Never prop-drill state. Child widgets read providers directly with ref.watch / ref.read / ref.listen. Do not pass entity / state / notifier instances through constructors. Constructor params allowed: immutable IDs (for routing/lookup), callbacks, Key, and primitive props on leaf atoms. ConsumerState may own lifecycle handles, not provider-derived *Cache/*Source/*DayStart fields; use computed providers or local build values. Lint: riverpod_consumer_state_derived_cache.
  1. Use a mixin when the same behavior appears in 2+ classes. Extract to a mixin with an on clause (e.g. mixin RetryMixin on AsyncNotifier<X>). Suffix the name with Mixin. Copy-paste sharing across notifiers, widgets, or services is forbidden — replace with a mixin.
  1. Storage SDK calls live in Local Datasource, never in Notifier. Hive (Hive.openBox, box.get/put/delete, Hive.box), SharedPreferences, flutter_secure_storage, dart:io file ops, path_provider directory access — all live behind a Local<X>Datasource interface, called by <X>Repository. Notifiers and widgets never import hive_ce / shared_preferences / flutter_secure_storage / dart:io / path_provider.
  1. Primitives → core/extensions/. Never inline. DateTime / String / int / double / num / Duration / Iterable / BuildContext ops (capitalize, timeAgo, currency, percent, clamp, format) in core/extensions/{type}_extensions.dart, barrel extensions.dart. Call .timeAgo / .capitalized / .asCurrency / .clamped(...) / .pluralized(...). Forbidden: '${s[0].toUpperCase()}${s.substring(1)}', DateTime.now().difference(...), DateTime.now().toUtc(), DateTime.timestamp(), DateTimeX.nowLocal().startOfDay, DateTimeX.nowLocal().calendarDaysBefore(...), NumberFormat.currency(...).format(...), inline .clamp(...). Raw executable strings and numbers are magic literals; move them to named constants, Value Objects, or semantic helpers. Current time helpers live in DateTimeX (nowUtc, nowLocal); current-day boundaries such as nowLocalStartOfDay and repeated local calendar windows such as "60 days ago" get semantic DateTimeX helpers. Calendar-day helpers reconstruct date components; they do not subtract Duration(days: ...) across DST-sensitive local dates. Persisted/server timestamps MUST use UTC helpers, and local calendar bucketing of stored timestamps MUST convert to local first. Lints: datetime_now_requires_timezone_intent, avoid_magic_literals (suppress with a comment only when local raw time or literal ownership is intentional and app-specific). Why: SSOT — one fix updates every call site. Apply: 2+ uses → extension. Domain entities NEVER import core/extensions/ (outer dep, arch_domain_import ERROR). Domain derive via entity getter (one-off) OR Value Object (cross-entity — Rule 12). See [extensions-utilities.md](references/extensions-utilities.md).
  1. Wrap domain primitives in Value Objects. Domain-meaning double/int/String (unit, currency, measure, identity, format) → sealed Freezed VO in /domain/values/. Raw redirects PRIVATE (._meters/._raw); public factories MUST contain explicit guards in body (if (v.isNaN) throw ArgumentError.value(...), if (!v.isFinite) throw ..., domain assertions), NEVER passthrough (factory X.unit(T v) => X._unit(v); is rejected — same risk as a public raw redirect). No named primitive factories on domain entities — convert at data/notifier/import boundaries. No hand-written copyWith in /domain/. Hive collision: Hive Models in /data/models/ hold primitives only; VOs live on domain Entity, mapper bridges. Never change ctor param types or order on a @GenerateAdapters-registered class with shipped user data — silent box corruption, dart analyze blind to disk. Apply: primitive in 2+ entities → VO. Bare double distanceMeters at entity boundary = smell. See [value-objects.md](references/value-objects.md), [hive-persistence.md](references/hive-persistence.md). Lints: vo_public_raw_constructor (catches public redirect AND passthrough), domain_entity_primitive_factory, domain_custom_copy_with, hive_field_no_vo_type.
  1. Keep typed GoRouter routes as the navigation SSOT. Define routes once with go_router_builder, then navigate with generated route helpers such as SomeRoute(...).go(context) and SomeRoute(...).push<T>(context). Keep route paths inside route definitions and generated helpers. Local sheets/dialogs use semantic helpers and Navigator.pop for dismissal. Navigation lints enforce typed routes, local modal helpers, and typed fallback behavior.

Trigger Map

Before writing code in any row below, output Reading: <ref-name> and read the listed reference(s).

| Touching | Read | |---|---| | Notifier, AsyncNotifier, mutation method, ref.read / ref.watch / ref.listen, `_ensur

Compartilhar X LinkedIn