Feature-first structure
Organizing a codebase by business capability at the top level, with the technical layers nested inside each capability, rather than by layer at the top with features scattered through them. Held from flutter-large-app-structure.
lib/features/authentication/{presentation,domain,data}
lib/features/profile/…
lib/features/checkout/…
The argument
Layer-first layouts spread one capability across the tree: “A single business capability now spans the entire project structure.” Feature-first puts the parts of a capability together, which gives the capability an owner and makes a change local.
The three layers, once you are inside a feature
- Presentation — widgets emit intent, state management orchestrates.
- Domain — business rules plus repository abstractions, infrastructure-agnostic.
- Data — the implementation: HTTP, database, serialization.
The invariant: “Business rules shouldn’t depend directly on HTTP clients, databases, or serialization details.” Everything else in the pattern is in service of that one direction of dependency.
State ownership is the load-bearing rule
Features own their state; the global container holds only genuinely cross-cutting concerns — authentication, theme, localization. Dependencies arrive by constructor injection so they are visible in the signature, and service locators reached from deep inside a widget are the named anti-pattern.
Compare micro-frontends, which reaches the same conclusion about global state from the other end of the scale: “avoid global state; it creates a lot of complexity.” One source is talking about a team’s folders and the other about an organization’s deployables, and they agree.
Same thesis, one scale down
This is application-architecture‘s founding claim in miniature: “Large applications rarely fail
because they lack patterns. They fail because ownership boundaries become unclear.” Where
micro-frontends draws the boundary at a deployable unit, feature-first draws it at a folder — and the
folder has no enforcement behind it. Nothing stops a widget importing across features except review, or
an architecture-testing tool of the kind micro-frontends-migration names (ts-arch).
That asymmetry is the open question this page leaves. A micro-frontend boundary is enforced by deployment; a feature boundary is enforced by discipline. No source here compares how well each holds.
A caution the source itself gives
“Most importantly, evolve architecture incrementally.” The article presents a complete structure and tells the reader not to adopt it whole.
Related
application-architecture · micro-frontends · flutter-large-app-structure · synthesis