<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ali El-Khatib</title>
    <description>The latest articles on DEV Community by Ali El-Khatib (@alielkhatib).</description>
    <link>https://dev.to/alielkhatib</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4099193%2Fc8b02788-2653-4090-8c19-846f4485eb27.png</url>
      <title>DEV Community: Ali El-Khatib</title>
      <link>https://dev.to/alielkhatib</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alielkhatib"/>
    <language>en</language>
    <item>
      <title>Architecting a Production-Grade Flutter Monorepo: LEGO Modular Boundaries, Melos &amp; bloc_signals</title>
      <dc:creator>Ali El-Khatib</dc:creator>
      <pubDate>Fri, 28 Aug 2026 15:32:44 +0000</pubDate>
      <link>https://dev.to/alielkhatib/architecting-a-production-grade-flutter-monorepo-lego-modular-boundaries-melos-blocsignals-bf</link>
      <guid>https://dev.to/alielkhatib/architecting-a-production-grade-flutter-monorepo-lego-modular-boundaries-melos-blocsignals-bf</guid>
      <description>&lt;p&gt;When scaling Flutter applications from a hobby project to an enterprise-grade codebase, teams almost always hit one of two architectural extremes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Monolithic Mess:&lt;/strong&gt; All business logic, HTTP clients, and UI widgets are dumped into one or two folders. Global state is everywhere, modules are tightly coupled, and making a change in one screen breaks three others.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The "Over-Abstracted" Clean Architecture:&lt;/strong&gt; In an attempt to follow Clean Architecture strictly, developers create 15 nested folders (data sources, raw DTOs, mappers, domain entities, use cases, presenters) just to display a simple settings toggle.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To solve this dilemma, I designed and open-sourced &lt;strong&gt;&lt;a href="https://github.com/Ali-El-Khatib/flutter-production-starter" rel="noopener noreferrer"&gt;Flutter Production Starter&lt;/a&gt;&lt;/strong&gt; — a modular, feature-first monorepo template built for real-world development speed and long-term maintainability.&lt;/p&gt;

&lt;p&gt;In this article, I’ll walk you through the architectural principles, dependency boundaries, and modern stack choices behind this starter.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧱 The Core Philosophy: "LEGO" Modular Boundaries
&lt;/h2&gt;

&lt;p&gt;The fundamental rule of this architecture is &lt;strong&gt;LEGO Modularity&lt;/strong&gt;: every feature should be a self-contained building block with a clear responsibility, minimal coupling, and an intentional public API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌───────────────────────────────────────────────┐
│                  APPLICATION                  │
│ Bootstrap • Config • DI • Routing • Observers │
└───────────────────────┬───────────────────────┘
                        │
                        ▼
┌───────────────────────────────────────────────┐
│               FEATURE MODULES                 │
│ Auth │ Profile │ Home │ Settings │ Payments   │
└───────────────────────┬───────────────────────┘
                        │
                        ▼
┌───────────────────────────────────────────────┐
│                SHARED PACKAGES                │
│ app_core │ network │ storage │ design_system  │
└───────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. Feature-First Colocation
&lt;/h3&gt;

&lt;p&gt;Instead of organizing the entire codebase by layer (&lt;code&gt;data/&lt;/code&gt;, &lt;code&gt;domain/&lt;/code&gt;, &lt;code&gt;presentation/&lt;/code&gt;), all code belonging to a business capability is colocated in &lt;code&gt;apps/mobile/lib/features/&amp;lt;feature&amp;gt;/&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Public API Barrel Files
&lt;/h3&gt;

&lt;p&gt;A feature must &lt;strong&gt;never&lt;/strong&gt; reach into the private implementation files of another feature. Instead, features expose only intentional contracts through their root barrel file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Clean: Importing through the feature's public API&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:mobile/features/auth/auth.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ❌ Forbidden: Deep import into private data sources&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:mobile/features/auth/data/datasources/auth_remote_data_source.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚖️ Pragmatic Clean Architecture (3 Complexity Tiers)
&lt;/h2&gt;

&lt;p&gt;Clean Architecture should be applied &lt;strong&gt;where complexity justifies it&lt;/strong&gt;, not blindly everywhere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tier 1 — Simple Feature (e.g. &lt;code&gt;settings&lt;/code&gt;):&lt;/strong&gt; Presentation + State only. No need for use cases or DTOs when updating a local theme mode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier 2 — Medium Feature (e.g. &lt;code&gt;profile&lt;/code&gt;):&lt;/strong&gt; Entity contract, Repository implementation, DTO mapping, and presentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier 3 — Complex Feature (e.g. &lt;code&gt;auth&lt;/code&gt;):&lt;/strong&gt; Complete Clean Architecture with Use Cases, Remote Data Sources, Token Storage, and Route Guards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pluggability (e.g. &lt;code&gt;auth_v2&lt;/code&gt;):&lt;/strong&gt; Proves you can swap out an entire feature's underlying data/service layer behind its domain interface via Dependency Injection without modifying consumer code.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📁 Monorepo Structure with Melos
&lt;/h2&gt;

&lt;p&gt;Managing multiple packages in a single repository is powered by &lt;a href="https://melos.invertase.dev/" rel="noopener noreferrer"&gt;Melos&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/
├── apps/
│   └── mobile/              # Main app (Bootstrap, Environments, DI, Routes, Features)
├── packages/
│   ├── app_core/            # Result&amp;lt;T&amp;gt; monad, domain Failure taxonomy, Sanitized AppLogger
│   ├── app_network/         # Centralized Dio, interceptors, error mappers, ApiClient
│   ├── app_storage/         # SecureStorage, KeyValueStorage, TTL MemoryCache
│   ├── design_system/       # Tokens (Spacing, Radius), Light/Dark themes, Primitives
│   └── app_lints/           # Strict linting &amp;amp; static analysis configuration
├── melos.yaml               # Monorepo scripts (analyze, test, format, run)
└── ARCHITECTURE.md          # Architectural guide
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why Dedicated Shared Packages?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;app_core&lt;/code&gt;:&lt;/strong&gt; Pure Dart abstractions (&lt;code&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;Failure&lt;/code&gt;, sanitized logger) with zero Flutter/UI dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;app_network&lt;/code&gt;:&lt;/strong&gt; Centralized &lt;code&gt;Dio&lt;/code&gt; instance. Features never instantiate &lt;code&gt;Dio()&lt;/code&gt; directly. It owns token injection, exponential backoff retries, and &lt;strong&gt;automatic sensitive data redaction&lt;/strong&gt; (passwords and bearer tokens are never logged in plain text).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;design_system&lt;/code&gt;:&lt;/strong&gt; Standalone visual primitives, tokens (&lt;code&gt;AppSpacing&lt;/code&gt;, &lt;code&gt;AppRadius&lt;/code&gt;, &lt;code&gt;AppDurations&lt;/code&gt;), and complete Material 3 Light/Dark themes.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ Modern Technology Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;Library / Solution&lt;/th&gt;
&lt;th&gt;Rationale&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Routing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kaisel: ^1.1.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Strongly-typed declarative routing and route guards (&lt;code&gt;AuthRouteGuard&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;State&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;bloc_signals&lt;/code&gt; + &lt;code&gt;signals_flutter&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Fine-grained reactive signals without boilerplate.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;get_it&lt;/code&gt; + &lt;code&gt;injectable&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Constructor injection with compile-time code generation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Networking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dio: ^5.11.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Enterprise HTTP client encapsulated in &lt;code&gt;app_network&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Models&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;freezed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Immutable union states, DTOs, and copyable entities.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Feedback&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;toastification: ^3.2.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Clean presentation-only feedback and snackbars.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🛡️ Functional Error Pipeline
&lt;/h2&gt;

&lt;p&gt;Instead of leaking raw HTTP exceptions into widgets, the app uses a functional &lt;code&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt; and &lt;code&gt;Failure&lt;/code&gt; hierarchy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Fetching data cleanly with functional Result&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;loginUseCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;email:&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;password:&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;onSuccess:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toHome&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nl"&gt;onFailure:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;failure&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// FailureMessageResolver resolves friendly messages&lt;/span&gt;
    &lt;span class="n"&gt;feedback&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;showError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;failureResolver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;failure&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧪 Testing &amp;amp; CI
&lt;/h2&gt;

&lt;p&gt;A starter is only as good as its verification. Every package in the monorepo has automated tests and strict linting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run tests across all 6 packages simultaneously&lt;/span&gt;
melos run &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="c"&gt;# Check static analysis across the entire monorepo&lt;/span&gt;
melos run analyze
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub Actions CI is already pre-configured (&lt;code&gt;.github/workflows/ci.yml&lt;/code&gt;) to validate every commit and PR automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Try It Out
&lt;/h2&gt;

&lt;p&gt;The entire template is open-source under the MIT License!&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/Ali-El-Khatib/flutter-production-starter" rel="noopener noreferrer"&gt;https://github.com/Ali-El-Khatib/flutter-production-starter&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone the repository&lt;/span&gt;
git clone https://github.com/Ali-El-Khatib/flutter-production-starter.git

&lt;span class="c"&gt;# Bootstrap packages&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;flutter-production-starter
melos bootstrap

&lt;span class="c"&gt;# Run the app&lt;/span&gt;
melos run run:dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you find this architecture helpful for your Flutter projects, feel free to give it a ⭐ on GitHub and share your thoughts in the comments below! What architectural patterns do you prefer for large-scale Flutter apps?&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>architecture</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
