M.Sayed

// notes / 2026-08-14 · 6 min

Clean Architecture in Flutter That Survives Contact With Reality

Flutter / Architecture / BLoC

Most Clean Architecture tutorials stop at the folder diagram. The real test is six months later: can you add a feature without touching five layers? In Shop Admin I kept one rule above all others: the UI layer never imports the database, directly or indirectly.

Feature-first, not layer-first

Instead of top-level data/domain/presentation folders, every feature owns its own slice: shop/cart, shop/orders, admin/inventory. Shared code lives in core/ and earns its place there only after the second feature needs it.

  • One feature = one folder with data, domain and presentation inside.
  • Drift DAOs are the only classes allowed to touch SQL.
  • A sealed Result<T> type carries errors; try/catch lives at the boundary, not in widgets.
  • BLoC states are sealed classes, so the compiler tells you when a branch is unhandled.

What I would do differently

I would introduce the admin role gate earlier. Bolting role-based navigation on at the end forced a refactor of the router. Architecture is a sequence of cheap decisions made early, not expensive ones made late.

The UI never imports the database. Enforce that one import rule and most architecture debates disappear.

← All notes