# Flutter Architecture

> This skill should be used when making architectural decisions in Flutter, when choosing between state management patterns, when structuring a new feature, when asked about Clean Architecture in Flutter, or when evaluating Riverpod provider design. Provides architectural guidance and pattern references.

- Skill: `haruhikomotokawa/flutter-architecture` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add haruhikomotokawa/flutter-architecture`
- Raw SKILL.md: https://api.skillmd.com/api/skills/haruhikomotokawa/flutter-architecture/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-architecture

---


# Flutter Architecture Guide

## Architecture: Feature-First Clean Architecture

This project follows a feature-first directory structure with Clean Architecture layers inside each feature.

```
lib/features/{feature}/
├── data/
│   ├── datasources/      # Remote (API) and local (cache/DB) sources
│   ├── models/           # DTOs with fromJson/toJson
│   └── repositories/     # Implements domain repository interfaces
├── domain/
│   ├── entities/         # Pure Dart domain objects (no JSON, no Flutter)
│   ├── repositories/     # Abstract interfaces
│   └── usecases/         # Single-responsibility business logic
└── presentation/
    ├── providers/        # Riverpod providers and notifiers
    ├── screens/          # Full-page widgets
    └── widgets/          # Feature-local reusable widgets
```

Detailed patterns: see [references/riverpod-patterns.md](references/riverpod-patterns.md)
Clean Architecture detail: see [references/clean-arch.md](references/clean-arch.md)

## Layer Rules (Dependency Direction)

```
presentation → domain ← data
```

- `presentation` depends on `domain` (entities, use cases, repository interfaces)
- `data` implements `domain` interfaces
- `domain` has zero Flutter or data-layer imports
- `presentation` never imports from `data` directly

## State Management: Riverpod

Preferred provider types by use case:

| Use Case | Provider Type |
|---|---|
| Synchronous computed value | `Provider` |
| Async data (read-only, no mutation) | `FutureProvider` / `StreamProvider` |
| Mutable async state | `AsyncNotifierProvider` |
| Mutable sync state | `NotifierProvider` |
| Single-use actions (not state) | `ref.read(notifierProvider.notifier).method()` |

## Navigation

Use `go_router` for declarative routing:
- Define all routes in a single `router.dart` file
- Use typed route classes when go_router codegen is available
- Pass only IDs through routes; load entities in the destination screen via providers

## Error Handling

Use `Result` or `Either` type for repository return values:

```dart
// Domain layer
abstract class UserRepository {
  Future<Result<User, AppError>> getUser(String id);
}
```

Do NOT throw exceptions across layer boundaries. Catch at the data layer, return failures.

## When to Deviate

These are defaults, not laws. Deviating is fine when:
- A feature is truly trivial (single screen, no business logic) — can live in `presentation/` only
- Third-party package imposes a different structure
- Performance requires bypassing the domain layer for hot paths

Document deviations in a comment or ADR.

