Skip to content
Development
Skill

/dart-rules

Dart/Flutter coding rules: style, patterns, security, testing. Triggers: .dart, pubspec.yaml, Flutter, Riverpod, Bloc, widget, StatelessWidget, StatefulWidget.

From plugin
ai-toolkit
161111 skills44 agents
Install
$ npx -y skills add softspark/ai-toolkit --skill dart-rules --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/dart-rules

Context preview

The summary Claude sees to decide when to auto-load this skill.

Dart/Flutter coding rules: style, patterns, security, testing. Triggers: .dart, pubspec.yaml, Flutter, Riverpod, Bloc, widget, StatelessWidget, StatefulWidget.

SKILL.md

dart-rules.SKILL.md
name: dart-rules
description: "Dart/Flutter coding rules: style, patterns, security, testing. Triggers: .dart, pubspec.yaml, Flutter, Riverpod, Bloc, widget, StatelessWidget, StatefulWidget."
effort: medium
user-invocable: false
allowed-tools: Read

Dart/Flutter Rules

These rules come from `app/rules/dart/` in ai-toolkit. They cover the project's standards for coding style, frameworks, patterns, security, and testing in Dart/Flutter. Apply them when writing or reviewing Dart/Flutter code.

Dart Coding Style

Naming

  • PascalCase: classes, enums, typedefs, extensions, mixins.
  • camelCase: variables, functions, methods, parameters, named constants.
  • snake_case: libraries, packages, directories, source files.
  • UPPER_SNAKE: not used in Dart. Use camelCase for constants.
  • Prefix private members with `_`: `_internalState`, `_helper()`.

Null Safety

  • Enable sound null safety (default since Dart 2.12).
  • Use `?` types only when null is semantically meaningful.
  • Use `!` operator sparingly. Prefer null checks or `??` fallback.
  • Use `late` keyword only when initialization is guaranteed before access.
  • Use `required` keyword for mandatory named parameters.

Classes

  • Use `const` constructors for immutable classes.
  • Use factory constructors for caching, subtype selection, or validation.
  • Use named constructors for clarity: `Point.fromJson(json)`.
  • Use `final` fields for immutable properties.
  • Use `@immutable` annotation on classes that should be immutable.

Functions

  • Use named parameters for functions with >2 parameters.
  • Use `required` for mandatory named parameters.
  • Use default values for optional parameters.
  • Use fat arrow (`=>`) for single-expression functions.
  • Always specify return types for public functions.

Collections

  • Use collection literals: `[]`, `{}`, `<String, int>{}`.
  • Use `if` and `for` inside collection literals for conditional/iterative building.
  • Use spread operator: `[...list1, ...list2]`.
  • Use `whereType<T>()` for type-safe filtering.
  • Prefer `const` collections when values are known at compile time.

Async

  • Use `async`/`await` for all asynchronous operations.
  • Return `Future<T>` from async functions. Never return `void`.
  • Use `Stream<T>` for continuous data (events, real-time updates).
  • Use `Future.wait()` for concurrent independent operations.
  • Use `Completer<T>` only when wrapping callback-based APIs.

Imports

  • Order: `dart:` SDK, `package:` external, relative project imports.
  • Use `show`/`hide` to limit import scope when names conflict.
  • Use `as` prefix for namespace conflicts: `import 'package:foo/foo.dart' as foo`.
  • Prefer relative imports within the same package.

Formatting

  • Use `dart format` (line length 80) for consistent formatting.
  • Use `dart analyze` for static analysis with default lint rules.
  • Use `analysis_options.yaml` with recommended lints: `flutter_lints` or `lints`.
  • Use trailing commas in multi-line argument lists for cleaner diffs.

Dart Frameworks

Flutter

  • Use `StatelessWidget` by default. Use `StatefulWidget` only for local state.
  • Use `const` constructors and `const` widgets for build optimization.
  • Use `Key` parameters for widgets in lists for correct diffing.
  • Extract large `build()` methods into smaller widget classes (not methods).
  • Use `Theme.of(context)` and `TextTheme` for consistent styling.

Navigation

  • Use `GoRouter` for declarative, type-safe routing.
  • Define routes as constants: `static const String home = '/home'`.
  • Use `ShellRoute` for persistent navigation bars across routes.
  • Use `context.go()` for navigation, `context.push()` for stacking.
  • Pass arguments via path parameters or `extra` for complex objects.

Networking

  • Use `dio` for HTTP with interceptors, retry, and cancellation.
  • Use `retrofit` (code gen) for type-safe REST client definitions.
  • Use interceptors for auth token injection and refresh logic.
  • Set timeouts on every request: `connectTimeout`, `receiveTimeout`.
  • Use `CancelToken` for cancelling in-flight requests on navigation.

JSON Serialization

  • Use `json_serializable` (+ `build_runner`) for generated `fromJson`/`toJson`. Default `fieldRename: FieldRename.none` uses Dart property names as-is — combined with Effective Dart `lowerCamelCase`, this produces `camelCase` JSON keys with zero configuration.
  • Flutter docs recommend: *"best if both server and client follow the same naming strategy"* ([Flutter — JSON and serialization](https://docs.flutter.dev/data-and-backend/serialization/json)). When they do, no mapping is needed.
  • When server uses a different convention, prefer `@JsonSerializable(fieldRename: FieldRename.snake)` at the class level (or globally in `build.yaml`) over sprinkling `@JsonKey(name:)` on every field. Community recommendation from the `json_serializable` docs and pub.dev guides.
  • Use individual `@JsonKey(name: '...')` only for exceptional cases: external API with mixed conventions, reserved Dart keyword collision (`class`, `is`, `new`), or legacy field rename during deprecation window. Document the reason in a comment.
  • For enum / status / permission values on the wire: `UPPER_SNAKE_CASE` is the cross-language community consensus (see `common/coding-style.md` — JSON Wire Format Conventions). Dart enum case names themselves stay `lowerCamelCase` per Effective Dart; map them to uppercase strings in `fromJson`/`toJson` (`value.toUpperCase()` + `switch`).
  • Write unit tests asserting both directions (`fromJson` + `toJson`) with explicit expected keys. Catches contract drift at CI time.

Local Storage

  • Use `shared_preferences` for simple key-value persistence.
  • Use `drift` (formerly Moor) for type-safe SQLite with reactive queries.
  • Use `hive` for fast, lightweight NoSQL local storage.
  • Use `flutter_secure_storage` for sensitive data (tokens, passwords).
  • Never store secrets in `shared_preferences` (not encrypted).

Dependency Injection

  • Use `get_it` for service locator pattern. Register at a
Read more
Ships withai-toolkit

Professional-grade AI coding toolkit with multi-platform support. Machine-enforced safety, 109 skills, 44 agents, expanded lifecycle hooks, persona presets, experimental opt-in plugin packs, and benchmark tooling — works with Claude Code, Claude Chat/Cowork,

Get the whole plugin