The 18-month refactor
The app works, it grows, and each new feature costs more than the last. The moment you should accelerate is the moment you rewrite.
Flutter / Firebase architecture — the layou-dev-kit
An architecture held up by good intentions doesn't hold. This one is split into packages whose dependencies are checked by the Dart compiler. If presentation imports data, it isn't a warning, a lint, or a review comment: it's a red error that blocks the build.
The 5 packages, and what each is allowed to see
The cost of no architecture
The app works, it grows, and each new feature costs more than the last. The moment you should accelerate is the moment you rewrite.
One person knows why that file exists. The knowledge lives in a head, not in the structure.
You debate indentation and naming while a Firestore call slips into a widget.
What it returns
An architecture promise with no mechanism is a slogan. For each one, here's what actually enforces it.
Add people without slowing the team down
The monorepo is split by layer, not by screen. Two devs on two features don't collide: they don't touch the same packages.
The blast radius of a change is known upfront
When a business rule moves, it moves inside domain. Nothing else compiles differently. That's what a held architecture buys: knowing what you're not breaking.
domain is pure: testable with no emulator, no Firebase, no widgetdataThe MVP and the V3 are the same codebase
Clean Architecture from day 1, even for an MVP. No throwaway code, so no rewrite exactly when the app finally starts working.
sealed class Failure + exhaustive switch — adding a failure case becomes a compile error everywhere it's missingEither on writes: the failure path lives in the signature, not in a forgotten try/catchFew chokepoints, so little to audit
An architecture doesn't secure an app — it decides how many places you must go through. That number is what makes an audit feasible.
status: pending document, a trigger processes it. One entry surface to govern instead of a fleet of HTTP endpoints.env. Client-side, envied injects them at compile timeFailure at the data boundaryThe rule
Each package declares its dependencies. This table isn't a team convention pinned to a wall: it's the real state of the pubspec.yaml files. A red cell is a broken build.
| Package… | core | domain | data | presentation | app |
|---|---|---|---|---|---|
| core | · | ✕ | ✕ | ✕ | ✕ |
| domain | ✓ | · | ✕ | ✕ | ✕ |
| data | ✓ | ✓ | · | ✕ | ✕ |
| presentation | ✓ | ✓ | ✕ | · | ✕ |
| app | ✓ | ✓ | ✓ | ✓ | · |
// ✅ OK — presentation → domain
import 'package:myapp_domain/auth/entities/app_user.dart';
// ❌ COMPILATION ERROR — data qui fuite dans presentation
import 'package:myapp_data/auth/datasources/auth_remote_datasource.dart'; Tooling
The rest runs through `custom_lint`. These are rules nobody has to defend in review — they fail on their own.
molecule_no_riverpod error connector_must_be_consumer error max_function_lines · 50 warning max_class_lines · 200 warning one_public_class_per_file warning And there's no escape hatch: disabling a rule with // ignore_for_file is forbidden by the kit. You refactor instead.
Before / after
| Without the dev-kit | With | |
|---|---|---|
| Forbidden import | It compiles (but it's broken) | Compilation error |
| Oversized widget | Nobody notices | Lint error at 200 lines |
| Molecule using Riverpod | It works | Lint error |
| Testing a widget | Mock hell | Zero mocks |
| New AI agent | Must re-read every convention | The compiler guides it |
Why it matters in 2026
An AI agent writes fast, and it cheats: a datasource imported into a widget, three classes in one file, a setState “because it's simpler.” The worst part is that it compiles — and quietly rots the codebase. What stops it isn't a longer prompt: it's a project where the shortcut doesn't compile. The agent gets the build error, understands the constraint, and corrects itself with no human in the loop. The compiler is the reviewer that never sleeps and never loses its context.
I don't need to trust the AI. The architecture itself is the guardrail.See the full delivery loop →
Honestly
Budget 2-3 days of Melos + package scaffolding on the first project, plus about a day to write the lint rules with their tests. After that it carries over from project to project.
A hackathon, a prototype you bin in two weeks: the 4 layers cost more than they return. It pays off when the code has to outlive its author.
The dev-kit contains no Firestore rules, no encryption policy, no GDPR compliance. It reduces the number of chokepoints — the audit and the rules remain work in their own right.
In detail
The dev-kit's 9 views: packages, layers, data flow, atomic design, Riverpod injection, errors, naming, UI, services. Keyboard navigation (1-9, Esc), or Auto Tour. The explorer's interface is in French.
Open fullscreen ↗Existing codebase or from-scratch start: we look at what holding this architecture at your place would cost, and what it would spare you.