# Architecture

> The layering rules for this Flutter codebase — feature-first structure, a pure Dart domain layer with no Flutter imports, Cubit or Bloc as the only bridge to presentation, and repositories behind interfaces. Use this whenever creating a new feature, adding any new file, deciding where code belongs, refactoring, or answering any question about project structure. Trigger it before writing the first…

- **Type:** Skill
- **Install:** `agentstack add skill-draz26648-flutter-claude-skills-architecture`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [draz26648](https://agentstack.voostack.com/s/draz26648)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [draz26648](https://github.com/draz26648)
- **Source:** https://github.com/draz26648/flutter_claude_skills/tree/main/plugins/flutter-code-quality/skills/architecture

## Install

```sh
agentstack add skill-draz26648-flutter-claude-skills-architecture
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Architecture

> **Profile first.** Read `.claude/flutter-profile.yaml` in the project root before
> placing any file. This skill is governed by `structure`, `state`, and `di`. With no
> profile, assume `structure: feature_first`, `state: bloc`, `di: get_it` — the layout
> below. Under `structure: layer_first` the layers are top-level directories and features
> are subdirectories inside them; the rules about which direction dependencies point are
> unchanged. Field list: `references/flutter-profile.md`.

Feature-first, three layers per feature. The rules exist to keep business logic testable
without a Flutter binding and swappable without touching the UI.

## Structure

```
lib/
├── core/                      # shared across features
│   ├── theme/                 # tokens, ThemeExtension
│   ├── network/               # Dio setup, interceptors
│   ├── errors/                # Failure types
│   └── widgets/               # genuinely shared widgets
└── features/
    └── wallet/
        ├── domain/            # pure Dart — no flutter/ imports at all
        │   ├── entities/
        │   ├── repositories/  # abstract interfaces only
        │   └── usecases/
        ├── data/
        │   ├── models/        # DTOs with fromJson/toJson
        │   ├── datasources/   # remote and local
        │   └── repositories/  # concrete implementations
        └── presentation/
            ├── cubit/
            ├── pages/
            └── widgets/
```

## The rules and why

**Domain imports nothing from Flutter.** Not `material.dart`, not `widgets.dart`, not
even for `Color` or `IconData`. The moment domain depends on Flutter it needs a binding
to test, and unit tests slow from milliseconds to seconds. If domain needs to express a
visual concept, it returns an enum and presentation maps it.

**Dependencies point inward.** Presentation knows domain. Data knows domain. Domain
knows nothing about either. A domain file importing from `data/` is the inversion this
structure exists to prevent.

**Repositories are interfaces in domain, implementations in data.** The Cubit depends on
the interface, which is what makes it testable with a mock instead of a live API.

**No `BuildContext` below presentation.** A use case taking a context has bound business
logic to the widget tree.

**Entities and models are separate.** The API's shape is not the app's shape. Models
handle JSON and live in data; entities express the domain and have no serialization code.
When the backend renames a field, exactly one file changes.

## Where things go

| Thing | Layer |
|---|---|
| "Transfer requires balance ≥ amount" | domain/usecases |
| "Balance shows two decimals" | presentation |
| "The API returns cents as an int" | data/models |
| "Failed transfers retry twice" | data/repositories |
| "The button is disabled while loading" | presentation/cubit |

## When to skip a use case

A use case that only forwards a call to a repository adds a file and no behaviour. For a
straight read with no rules, let the Cubit call the repository directly. Add the use case
when there is actual logic to hold — validation, orchestration across repositories,
business rules. Ceremony for its own sake makes a codebase harder to read, not more
correct.

## Common mistakes

- A `utils/` or `helpers/` folder at the root. It becomes a dumping ground within a
  month. Put the function next to what uses it.
- Shared widgets moved to `core/widgets/` on first reuse. Wait for the third usage —
  two usages that diverge later are cheaper to split than to un-merge.
- Cubits calling data sources directly, skipping the repository. That couples
  presentation to the transport layer.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [draz26648](https://github.com/draz26648)
- **Source:** [draz26648/flutter_claude_skills](https://github.com/draz26648/flutter_claude_skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-draz26648-flutter-claude-skills-architecture
- Seller: https://agentstack.voostack.com/s/draz26648
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
