<?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: José Vivas</title>
    <description>The latest articles on DEV Community by José Vivas (@jvivasb20).</description>
    <link>https://dev.to/jvivasb20</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1731210%2Fd58df4d8-8e46-470a-a19a-7147cffd8d55.jpeg</url>
      <title>DEV Community: José Vivas</title>
      <link>https://dev.to/jvivasb20</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jvivasb20"/>
    <language>en</language>
    <item>
      <title>Monorepos in Flutter: Scaling Shared Code Without Losing Your Mind</title>
      <dc:creator>José Vivas</dc:creator>
      <pubDate>Sat, 07 Jun 2025 22:01:04 +0000</pubDate>
      <link>https://dev.to/jvivasb20/monorepos-in-flutter-scaling-shared-code-without-losing-your-mind-d22</link>
      <guid>https://dev.to/jvivasb20/monorepos-in-flutter-scaling-shared-code-without-losing-your-mind-d22</guid>
      <description>&lt;p&gt;A key aspect of software development is code sharing—not just utility functions, but also business-critical logic like authentication flows, payment integrations, and domain-specific models. Monorepos help formalize this practice by turning shared code from a "nice-to-have" into a &lt;strong&gt;scalable architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I’ll walk through how to build a production-ready Flutter monorepo that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shares UI components and business logic&lt;/li&gt;
&lt;li&gt;Maintains consistent dependencies across apps and packages&lt;/li&gt;
&lt;li&gt;Streamlines testing and deployment through unified workflows&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why a Monorepo?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  When to Choose a Flutter Monorepo
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You're building &lt;strong&gt;multiple apps&lt;/strong&gt; (e.g., customer and admin apps)&lt;/li&gt;
&lt;li&gt;Your team maintains &lt;strong&gt;shared packages&lt;/strong&gt; used across different products&lt;/li&gt;
&lt;li&gt;You need &lt;strong&gt;atomic updates&lt;/strong&gt;, such as rolling out a security patch across all apps simultaneously&lt;/li&gt;
&lt;li&gt;Your CI/CD pipeline benefits from &lt;strong&gt;centralized control&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When &lt;em&gt;Not&lt;/em&gt; to Use a Monorepo
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Small projects&lt;/strong&gt; that don't require shared code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mixed tech stacks&lt;/strong&gt;, such as teams using both native iOS/Android and Flutter&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independent release cycles&lt;/strong&gt; where each app needs isolated versioning and deployment&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Pros and Cons
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Logic and UI reuse&lt;/strong&gt;: Share entire feature modules—including UI and logic—across apps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified dependency management&lt;/strong&gt;: Align versions of libraries like &lt;code&gt;riverpod&lt;/code&gt;, &lt;code&gt;dio&lt;/code&gt;, or &lt;code&gt;flutter_bloc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified CI/CD&lt;/strong&gt;: Trigger tests and builds for all affected packages when shared logic changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-project refactoring&lt;/strong&gt;: Modify shared APIs confidently, knowing all usage is in one place&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design system consistency&lt;/strong&gt;: Enforce a shared theme and component library across the organization&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Versioning complexity&lt;/strong&gt;: Releasing individual package versions may require tooling like Melos or custom scripts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency sprawl&lt;/strong&gt;: A breaking change in a low-level package can affect multiple apps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tooling overhead&lt;/strong&gt;: Requires tools like Melos, shell scripts, or IDE workspace configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository hygiene&lt;/strong&gt;: A large codebase demands strict conventions (e.g., &lt;code&gt;apps/&lt;/code&gt; and &lt;code&gt;packages/&lt;/code&gt; structure)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Project Structure Setup
&lt;/h2&gt;

&lt;p&gt;Start by defining a clear folder structure for your monorepo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter-monorepo/
├── apps/
│   ├── apps_1/
│   └── apps_2/
├── packages/
│   ├── package_1/
│   └── package_2/
├── melos.yaml
├── pubspec.yaml
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can scaffold your applications with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flutter create apps/apps_1 &lt;span class="nt"&gt;--org&lt;/span&gt; com.myorg.appname &lt;span class="nt"&gt;--project-name&lt;/span&gt; apps_1
flutter create apps/apps_2 &lt;span class="nt"&gt;--org&lt;/span&gt; com.myorg.appname &lt;span class="nt"&gt;--project-name&lt;/span&gt; apps_2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the root of the project, define a minimal &lt;code&gt;pubspec.yaml&lt;/code&gt; to include Melos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter_monorepo_tutorial&lt;/span&gt;

&lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;sdk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;=3.0.6&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;4.0.0"&lt;/span&gt;

&lt;span class="na"&gt;dev_dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;melos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^6.0.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then configure your &lt;code&gt;melos.yaml&lt;/code&gt; file to register packages and define workspace-wide tooling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter_monorepo_tutorial&lt;/span&gt;

&lt;span class="na"&gt;packages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;apps/**&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;packages/**&lt;/span&gt;

&lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;bootstrap&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;sdk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;=3.4.0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;4.0.0"&lt;/span&gt;

    &lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Shared runtime dependencies across all apps and packages&lt;/span&gt;
      &lt;span class="c1"&gt;# Example:&lt;/span&gt;
      &lt;span class="c1"&gt;# provider: ^6.1.1&lt;/span&gt;
      &lt;span class="c1"&gt;# dio: ^5.4.0&lt;/span&gt;

    &lt;span class="na"&gt;dev_dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Shared development dependencies&lt;/span&gt;
      &lt;span class="c1"&gt;# Example:&lt;/span&gt;
      &lt;span class="c1"&gt;# flutter_test:&lt;/span&gt;
      &lt;span class="c1"&gt;#   sdk: flutter&lt;/span&gt;
      &lt;span class="c1"&gt;# flutter_lints: ^3.0.0&lt;/span&gt;

&lt;span class="na"&gt;scripts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;format:all&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Format all Dart files to a 120-character line length&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dart format . -l &lt;/span&gt;&lt;span class="m"&gt;120&lt;/span&gt;

  &lt;span class="na"&gt;analyze:all&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run static analysis across all packages and apps&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter analyze .&lt;/span&gt;

  &lt;span class="na"&gt;test:all&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run all tests sequentially&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter test&lt;/span&gt;
    &lt;span class="na"&gt;exec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;orderDependents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;concurrency&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="na"&gt;packageFilters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;dependsOn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter_test&lt;/span&gt;
      &lt;span class="na"&gt;flutter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="na"&gt;build:release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build a release APK for target apps using predefined environment and flavor&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter build apk --release --target=lib/main_prod.dart --dart-define-from-file=.env --flavor=prod&lt;/span&gt;
    &lt;span class="na"&gt;exec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;failFast&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;packageFilters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;scope&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*app*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once configured, run &lt;code&gt;melos bootstrap&lt;/code&gt; to install dependencies and link local packages. You can then use the defined scripts to format, analyze, test, and build your workspace consistently.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Melos provides a solid foundation for managing Flutter monorepos at scale. A well-structured layout, unified dependency management, and reusable tooling help reduce maintenance overhead and speed up development across teams.&lt;/p&gt;

&lt;p&gt;A monorepo setup is not a fit for every team, but when applied in the right context, it becomes a powerful architecture for shared codebases.&lt;/p&gt;




&lt;h2&gt;
  
  
  More
&lt;/h2&gt;

&lt;p&gt;To go deeper or enhance your monorepo setup, consider exploring the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CI/CD with Codemagic&lt;/strong&gt;&lt;br&gt;
Codemagic supports monorepos natively and allows conditional builds and parallel pipelines. &lt;a href="https://blog.codemagic.io/flutter-monorepos/" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testing Pipelines&lt;/strong&gt;&lt;br&gt;
Combine &lt;code&gt;melos run&lt;/code&gt; with GitHub Actions (or similar CI tools) to execute tests only for changed packages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Very Good Ventures Templates&lt;/strong&gt;&lt;br&gt;
Explore production-ready monorepo templates and tooling from &lt;a href="https://cli.vgv.dev/docs/category/templates" rel="noopener noreferrer"&gt;Very Good Ventures&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code With Andrea&lt;/strong&gt;&lt;br&gt;
In-depth tutorials from &lt;a href="https://codewithandrea.com/" rel="noopener noreferrer"&gt;Code With Andrea&lt;/a&gt; cover architecture, modularization, and testing strategies in Flutter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;FVM (Flutter Version Management)&lt;/strong&gt;&lt;br&gt;
Helps medium-to-large teams manage and pin specific Flutter versions per app or package.&lt;a href="https://fvm.app/" rel="noopener noreferrer"&gt;Learn more&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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