# Flutter Conventions

> This skill should be used when working on Flutter or Dart code, when creating widgets, when writing Dart, when asked about Flutter patterns or conventions in this project. Provides Flutter/Dart coding conventions and standards.

- Skill: `haruhikomotokawa/flutter-conventions` (Agent Skill)
- Install (CLI): `npx skillmds@latest add haruhikomotokawa/flutter-conventions`
- Raw SKILL.md: https://api.skillmd.com/api/skills/haruhikomotokawa/flutter-conventions/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: HaruhikoMotokawa (https://skillmd.com/u/haruhikomotokawa)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/haruhikomotokawa/flutter-conventions

---


# Flutter / Dart Conventions

## File and Directory Structure

```
lib/
├── main.dart
├── app.dart                  # MaterialApp / root widget
├── core/                     # Shared utilities, constants, extensions
│   ├── constants/
│   ├── extensions/
│   └── utils/
├── features/                 # Feature-first organization
│   └── {feature}/
│       ├── data/             # Repositories, data sources, DTOs
│       ├── domain/           # Entities, use cases, interfaces
│       └── presentation/     # Widgets, screens, view models / providers
└── shared/                   # Reusable UI components
    └── widgets/
```

## Naming Conventions

| Element | Convention | Example |
|---|---|---|
| Files | `snake_case.dart` | `user_profile_card.dart` |
| Classes | `PascalCase` | `UserProfileCard` |
| Variables / fields | `camelCase` | `userName` |
| Constants | `camelCase` (not SCREAMING) | `defaultTimeout` |
| Private fields | `_camelCase` | `_isLoading` |
| Providers (Riverpod) | `camelCase` + `Provider` suffix | `userProfileProvider` |

## Widget Conventions

- Use `const` constructors whenever no runtime-varying field exists
- Always add `{super.key}` to the constructor
- Extract subtrees exceeding ~50 lines into named widget classes
- Never put business logic in `build()` — call methods or read providers only
- Access `Theme` via `Theme.of(context)` — do not hardcode colors

```dart
// Good
class UserProfileCard extends StatelessWidget {
  const UserProfileCard({super.key, required this.user});
  final User user;
  ...
}

// Bad — missing const, missing key
class UserProfileCard extends StatelessWidget {
  UserProfileCard({required this.user});
  ...
}
```

## State Management (Riverpod)

- `ref.watch` only inside `build()` or `HookWidget.build()`
- `ref.read` only in event handlers / callbacks
- `ref.listen` for side effects (navigation, snackbars)
- Keep providers small and single-responsibility
- Prefer `AsyncNotifierProvider` over `FutureProvider` for mutable async state

## Null Safety

- Avoid `!` unless null is provably impossible; add a comment explaining why
- Prefer `?.`, `??`, and null-aware patterns
- Prefer non-nullable types in public APIs
- Never use `dynamic` unless interacting with untyped external data (JSON deserialization)

## Imports

Use `package:` imports for all cross-package and intra-package imports.
Avoid relative imports for files outside the same directory.

```dart
// Good
import 'package:my_app/features/auth/domain/user.dart';

// Bad
import '../../../features/auth/domain/user.dart';
```

## Testing

- Widget tests go in `test/` mirroring the `lib/` structure
- Name test files `{source_file}_test.dart`
- Each `group()` corresponds to one class
- Use `testWidgets` for widgets, `test` for pure logic
- Mock dependencies with `mocktail` (preferred) or `mockito`

## Useful Commands

- `/flutter-widget <WidgetName>` — scaffold widget + test
- `/flutter-test <path>` — generate tests for existing code
- `/flutter-l10n <key> <text>` — add localization key

