{"id":1895,"date":"2026-07-15T18:48:07","date_gmt":"2026-07-15T18:48:07","guid":{"rendered":"https:\/\/dev95.site\/revisiting-the-jet-ios-modular-architecture-in-2026\/"},"modified":"2026-07-15T18:48:07","modified_gmt":"2026-07-15T18:48:07","slug":"revisiting-the-jet-ios-modular-architecture-in-2026","status":"publish","type":"post","link":"https:\/\/dev95.site\/ar\/revisiting-the-jet-ios-modular-architecture-in-2026\/","title":{"rendered":"Revisiting the JET iOS Modular Architecture in 2026"},"content":{"rendered":"<div id=\"dev95-3127626989\" class=\"dev95-- dev95-entity-placement\"><script async=\"async\" data-cfasync=\"false\" src=\"https:\/\/pl27862732.profitableratecpmnetwork.com\/2ad7a50e0bbc23ac6801d7b77c501463\/invoke.js\"><\/script>\r\n<div id=\"container-2ad7a50e0bbc23ac6801d7b77c501463\"><\/div><\/div><div>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-text\"><i><em class=\"italic\" style=\"white-space: pre-wrap;\">Originally published on the\u00a0<\/em><\/i><a href=\"https:\/\/medium.com\/justeattakeaway-tech\/revisiting-the-just-eat-takeaway-ios-modular-architecture-in-2026-752142331755?ref=albertodebortoli.com\" rel=\"noreferrer\"><i><em class=\"italic\" style=\"white-space: pre-wrap;\">Just Eat\u00a0Takeaway\u00a0Engineering Blog<\/em><\/i><\/a><i><em class=\"italic\" style=\"white-space: pre-wrap;\">.<\/em><\/i><\/div>\n<\/div>\n<p><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/storage.ghost.io\/c\/ae\/f4\/aef4d625-32a2-417b-86f4-22c70a9b47a1\/content\/images\/2026\/07\/modular_arch_2026.png?w=1280&#038;ssl=1\" alt=\"Revisiting the JET iOS Modular Architecture in 2026\"><\/p>\n<p>When I published <a href=\"https:\/\/albertodebortoli.com\/2019\/12\/19\/modular-ios-architecture-at-just-eat\/\">Modular iOS Architecture @ Just Eat<\/a> in December 2019, modularisation was still a relatively novel concept in iOS development. We had been at it since 2016, driven by specific organisational needs: bringing together country apps onto a single platform and apply Conway&#8217;s Law rather than the more common motivation of build-time parallelisation. The article described the architecture we had settled on after three years of iteration: a directed acyclic graph of modules, partitioned into three broad groups (domain, core and shared), with strict rules against peer-module dependencies.<\/p>\n<p>In the seven years since, a great deal has changed. CocoaPods was fully replaced by Swift Package Manager. The monorepo approach we were tentatively advocating for became the unquestioned standard in the industry. The team grew substantially, the product expanded into new markets, and the number of modules roughly doubled. What didn&#8217;t change was the fundamental shape of the graph or the core dependency rules governing it.<\/p><div id=\"dev95-11046978\" class=\"dev95- dev95-entity-placement\"><center>\r\n<script>\r\n  atOptions = {\r\n    'key' : '4ba6b6513c00e0ba76511f798ae56401',\r\n    'format' : 'iframe',\r\n    'height' : 50,\r\n    'width' : 320,\r\n    'params' : {}\r\n  };\r\n<\/script>\r\n<script src=\"https:\/\/www.highrevenueformat.com\/4ba6b6513c00e0ba76511f798ae56401\/invoke.js\"><\/script>\r\n\t<\/center><\/div>\n<p>Yet in late 2025, a seemingly small problem \u2014 a UI component with nowhere to live in the existing model \u2014 surfaced a conceptual ambiguity that had been quietly accumulating for years. Resolving it led to the refresh described in this article.<\/p>\n<hr>\n<h2 id=\"what-the-2019-model-got-right\">What the 2019 model got right<\/h2>\n<p>Before describing what changed, it&#8217;s worth being precise about what didn&#8217;t. Several properties of the 2019 architecture proved robust enough to survive intact:<\/p>\n<ul>\n<li><strong>The graph must be acyclic.<\/strong> Dependencies flow in one direction, always. No module may depend \u2014 directly or transitively \u2014 on a module that depends on it. This means respecting the Acyclic Dependencies Principle.<\/li>\n<li><strong>Feature modules do not depend on other feature modules.<\/strong> Anything two features need to share is extracted into a lower-level module. This prevents the lateral coupling that tends to develop over time when features are allowed to reach into each other.<\/li>\n<li><strong>Each module exposes a facade.<\/strong> Modules should be deep with a narrow, stable public interface. The internal architecture of a module is unconstrained and teams may use MVVM, TCA, or anything else, provided they do so behind the facade.<\/li>\n<li><strong>Demo apps are first-class citizens.<\/strong> Every module ships with a standalone demo application. This remains one of the most impactful practices we have: it forces good API design, serves as living documentation, and provides a fast local feedback loop during development.<\/li>\n<\/ul>\n<p>The 2026 refresh doesn&#8217;t replace the 2019 architecture and it&#8217;s rather a refinement of the vocabulary and an extension of the rules to cover cases the original model didn&#8217;t address.<\/p>\n<hr>\n<h2 id=\"the-crack-that-started-the-conversation\">The crack that started the conversation<\/h2>\n<p>The problem that triggered the rethink was a component called <code>CountdownTimer<\/code>. It is a countdown UI component built on top of our design library and not part of the JET design system (<a href=\"https:\/\/pie.design\/?ref=albertodebortoli.com\">PIE<\/a>), used by both the <code>Checkout<\/code> and <code>Restaurant<\/code> domain modules.<\/p>\n<p>Under the 2019 model, every module belonged to one of three groups: <em>domain<\/em> (feature-specific, may change frequently), <em>shared<\/em> (pure utilities with no local dependencies) and <em>core <\/em>(like shared but only imported at app-level). Domain modules could depend on shared modules, but not on other domain modules. Shared and core modules could not depend on anything local. Modules in each group can depend on third-party dependencies.<\/p>\n<p><code>CountdownTimer<\/code> fit neither group cleanly:<\/p>\n<ul>\n<li>It can&#8217;t be <em>shared<\/em> because it depends on PIE. Under the 2019 definition, shared modules have no dependencies.<\/li>\n<li>It can&#8217;t live inside <code>Checkout<\/code> or <code>Restaurant<\/code> because the other would need it too, creating a domain \u2192 domain dependency \u2014 which is forbidden.<\/li>\n<\/ul>\n<p><!--kg-card-begin: html--><\/p>\n<pre class=\"mermaid\">\nflowchart TB\n    Checkout --&gt; CountdownTimer\n    Restaurant --&gt; CountdownTimer\n<\/pre>\n<p><!--kg-card-end: html--><\/p>\n<p>The model had no concept for a module that has dependencies <em>and<\/em> is shared across domain modules. CountdownTimer was first the crack and it didn&#8217;t take long for other similar modules to appear highlighting the need for revisiting the design.<\/p>\n<hr>\n<h2 id=\"a-note-on-the-cross-domain-proposal\">A note on the cross-domain proposal<\/h2>\n<p>A colleague proposed an elegant-looking fix: introduce a third layer called <em>cross-domain<\/em>, sitting between domain and shared. The layering would become:<\/p>\n<pre><code>domain      \u2192  cross-domain   \u2192  shared\nCheckout       CountdownTimer    DateFormatting\nRestaurant     DynamicLayout     ErrorUtilities<\/code><\/pre>\n<p><code>CountdownTimer<\/code> would live in cross-domain: it could depend on shared modules, and domain modules could depend on it. The approach was implemented: layer rules were encoded in a YAML config file, and a new CLI tool was introduced to enforce them. For a moment it looked like the problem was solved.<\/p>\n<p>I revisited the proposal shortly after and something felt off. The more I thought about it, the more I realised the cross-domain layer was a positional label rather than a meaningful category. <code>CountdownTimer<\/code> is not &#8220;cross-domain&#8221; because of anything intrinsic to what it is. It was labelled &#8220;cross-domain&#8221; purely because of how many modules happened to use it and because it had a dependency on PIE. If a future project used it from only one feature module, would we move it back to domain? The category was defined by the topology rather than the purpose.<\/p>\n<p>The same confusion was visible elsewhere. We had long kept a distinction between &#8220;Core&#8221; modules (<code>APIClient<\/code>, <code>NavigationEngine<\/code>) and &#8220;Shared&#8221; modules (<code>DateFormatting<\/code>, <code>ErrorUtilities<\/code>). Both sat near the bottom of the graph, but they occupied separate mental buckets with no formal rule distinguishing them. Core and shared were a positional label and not a purposeful one.<\/p>\n<p>I believed that the right fix was not a new positional layer but rather a different categorisation model altogether.<\/p>\n<hr>\n<h2 id=\"the-2026-model-categorise-by-purpose\">The 2026 model: categorise by purpose<\/h2>\n<p>The refreshed model categorises every component by its <em>purpose<\/em> (the role it plays) rather than by where it happens to sit in the dependency graph. The topology is then a consequence of the rules and not an input to them.<\/p>\n<p>There are five categories. Three describe components we own; two describe third-party packages.<\/p>\n<h3 id=\"first-party-categories\">First-party categories<\/h3>\n<ul>\n<li><strong>App<\/strong> \u2014 iOS applications and their extensions: the consumer app, demo apps, notification extensions, widgets, etc. These are the roots of the graph; nothing depends on an App.<\/li>\n<li><strong>Feature<\/strong> \u2014 what we used to call &#8220;domain&#8221;: an area of the product with UI belonging to a business process. E.g. <code>Checkout<\/code>, <code>Orders<\/code>, <code>Restaurant<\/code>, <code>Account<\/code>. Deep modules implementing a facade pattern; they change frequently and are consumed only by the App.<\/li>\n<li><strong>Foundation<\/strong> \u2014 modules with a single, clear responsibility: <code>DateFormatting<\/code>, <code>ErrorUtilities<\/code>, <code>APIClient<\/code>, <code>NavigationEngine<\/code>, <code>Logger<\/code>, <code>CountdownTimer<\/code>. The key move here is the unification of what were previously two separate buckets (Core and Shared) into one category. <code>APIClient<\/code> and <code>DateFormatting<\/code> are both Foundation modules <em>because of their purpose<\/em> (a single, clear responsibility), not because of their depth in the graph. It follows naturally that Foundation modules may depend on other Foundation modules.<\/li>\n<\/ul>\n<p>The Foundation category is also where <code>CountdownTimer<\/code> lands. It has a single clear responsibility and depends on PIE, which is itself a Foundation module (a design library with a single clear responsibility). With this new model, no new layer are needed.<\/p>\n<h3 id=\"third-party-categories\">Third-party categories<\/h3>\n<p>A longstanding gap in the original model was that third-party packages were outside the rules entirely. Nothing prevented a Foundation module from pulling in third-party dependencies, even though we all agreed this was bad practice. The 2026 model closes that gap by giving third-party packages their own categories:<\/p>\n<ul>\n<li><strong>SDK<\/strong> \u2014 a heavyweight third-party capability that encapsulates an entire domain and should sit behind an injection boundary. <code>Firebase<\/code>, <code>BranchSDK<\/code>, <code>GoogleTagManager<\/code>, <code>SnowplowTracker<\/code>. The rule: only an App may depend on SDKs. Features and Foundations may not. This is the <em>enforced<\/em> form of &#8220;place large third-party dependencies high in the graph, behind an abstraction&#8221; \u2014 a principle that existed in 2019 as guidance and exists in 2026 as a hard constraint.<\/li>\n<li><strong>Utility<\/strong> \u2014 a small, stable third-party helper safe to depend on widely. <code>Alamofire<\/code>, <code>Nuke<\/code>, <code>Stateful<\/code>, <code>PhoneNumberKit<\/code>. A Utility behaves like a Foundation leaf: App, Feature, and Foundation modules can all depend on one.<\/li>\n<\/ul>\n<p>The SDK\/Utility split mirrors the first-party Feature\/Foundation split: SDKs are heavyweight capabilities we keep at arm&#8217;s length; Utilities are low-level building blocks. The distinction is recorded in a package catalogue file (that we use for a variety of operations on the stack) that lists all third-party dependencies, where each entry carries a <code>category<\/code> field:<\/p>\n<pre><code class=\"language-json\">{ \"name\": \"Firebase\",  \"category\": \"sdk\"        }\n{ \"name\": \"Alamofire\", \"category\": \"utility\"    }\n{ \"name\": \"PIE\",       \"category\": \"foundation\" }<\/code><\/pre>\n<p>First-party remote packages follow the same category rules as local modules. This is the case of PIE which is consumed as a remote first-party package and is categorised as a <code>Foundation<\/code> module.<\/p>\n<hr>\n<h2 id=\"two-rules\">Two rules<\/h2>\n<p>The architecture enforces exactly two rules. Everything else follows from them.<\/p>\n<p><strong>Rule 1 \u2014 No cyclic dependencies:<\/strong> The graph must be a DAG. A\u2192B\u2192\u2026\u2192A in any form is rejected, detected via depth-first search.<\/p>\n<p><strong>Rule 2 \u2014 The category matrix:<\/strong> Every dependency edge from component <code>u<\/code> to component <code>v<\/code> must be permitted by:<\/p>\n<table>\n<thead>\n<tr>\n<th>From \u2193 \/ To \u2192<\/th>\n<th style=\"text-align:center\">App<\/th>\n<th style=\"text-align:center\">Feature<\/th>\n<th style=\"text-align:center\">Foundation<\/th>\n<th style=\"text-align:center\">SDK<\/th>\n<th style=\"text-align:center\">Utility<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>App<\/strong><\/td>\n<td style=\"text-align:center\">\u2717<\/td>\n<td style=\"text-align:center\">\u2713<\/td>\n<td style=\"text-align:center\">\u2713<\/td>\n<td style=\"text-align:center\">\u2713<\/td>\n<td style=\"text-align:center\">\u2713<\/td>\n<\/tr>\n<tr>\n<td><strong>Feature<\/strong><\/td>\n<td style=\"text-align:center\">\u2717<\/td>\n<td style=\"text-align:center\">\u2717<\/td>\n<td style=\"text-align:center\">\u2713<\/td>\n<td style=\"text-align:center\">\u2717<\/td>\n<td style=\"text-align:center\">\u2713<\/td>\n<\/tr>\n<tr>\n<td><strong>Foundation<\/strong><\/td>\n<td style=\"text-align:center\">\u2717<\/td>\n<td style=\"text-align:center\">\u2717<\/td>\n<td style=\"text-align:center\">\u2713<\/td>\n<td style=\"text-align:center\">\u2717<\/td>\n<td style=\"text-align:center\">\u2713<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Several consequences are worth calling out explicitly:<\/p>\n<ul>\n<li><strong>Feature \u2192 Feature remains forbidden.<\/strong> This is the unchanged core of the 2019 rule. Anything two features need to share is extracted into a Foundation module or coordinated through an upstream abstraction in the App.<\/li>\n<li><strong>Foundation \u2192 Foundation is now explicitly allowed.<\/strong> This is the deliberate relaxation. It resolves the Core\/Shared ambiguity and removes the need for any special treatment of modules.<\/li>\n<li><strong>App \u2192 SDK is the only entry point for heavyweight third-party SDKs.<\/strong> A Feature or Foundation depending on <code>Firebase<\/code> or <code>BranchSDK<\/code> will fail validation. The SDK is a dependency of the App, and Feature modules receive its capabilities through an injected abstraction.<\/li>\n<li><strong>Utility modules are Foundation-equivalent for third-party packages.<\/strong> A Utility may be depended on by any first-party component, exactly as a Foundation module can.<\/li>\n<li><strong>SDK and Utility nodes are leaves.<\/strong> Their outgoing edges are not modelled or enforced since we do not control what third-party components depend on.<\/li>\n<\/ul>\n<p>The category matrix is hardcoded in a validator CLI, not read from a configuration file. This was a deliberate choice: the matrix encodes an architectural law derived from ADP (Acyclic Dependency Principle), SDP (Stable Dependency Principle), and DIP (Dependency Inversion Principle).<\/p>\n<p>The following diagram shows a representative slice of our module graph, with edges colour-coded by allowed category pair:<\/p>\n<p><!--kg-card-begin: html--><\/p>\n<pre class=\"mermaid\">\nflowchart TB\n    subgraph L0[\"L0\"]\n        App\n    end\n    subgraph L1[\"L1\"]\n        APIClient\n        Account\n        Checkout\n        NavigationEngine\n        Firebase\n        SnapshotTesting\n    end\n    subgraph L2[\"L2\"]\n        CountdownTimer\n        DateFormatting\n        Stateful\n        KeychainAccess\n    end\n    subgraph L3[\"L3\"]\n        PIE\n    end\n    App --&gt; Account\n    App --&gt; Checkout\n    App --&gt; APIClient\n    App --&gt; NavigationEngine\n    App --&gt; Firebase\n    Checkout --&gt; CountdownTimer\n    Account --&gt; PIE\n    APIClient --&gt; DateFormatting\n    CountdownTimer --&gt; PIE\n    NavigationEngine --&gt; Stateful\n    Account --&gt; KeychainAccess\n    App --&gt; SnapshotTesting\n    linkStyle 0,1 stroke:blue\n    linkStyle 2,3 stroke:green\n    linkStyle 4 stroke:magenta\n    linkStyle 5,6 stroke:orange\n    linkStyle 7,8 stroke:brown\n    linkStyle 9 stroke:pink\n    linkStyle 10 stroke:teal\n    linkStyle 11 stroke:grey\n<\/pre>\n<p><!--kg-card-end: html--><\/p>\n<p>Blue: App \u2192 Feature<br \/>Green: App \u2192 Foundation<br \/>Magenta: App \u2192 SDK<br \/>Grey: App \u2192 Utility<br \/>Orange: Feature \u2192 Foundation<br \/>Teal: Feature \u2192 Utility<br \/>Brown: Foundation \u2192 Foundation<br \/>Pink: Foundation \u2192 Utility<\/p>\n<hr>\n<h2 id=\"layers-are-a-derived-view-not-an-authored-property\">Layers are a derived view, not an authored property<\/h2>\n<p>One of the more significant conceptual shifts in the 2026 model is the distinction between <em>category<\/em> \u2014 an authored, stable property \u2014 and <em>layer<\/em> \u2014 a computed, dynamic one.<\/p>\n<p><strong>Category<\/strong> is what you write: modules are tagged with the <code>category<\/code> property once, and that tag doesn&#8217;t change unless the module&#8217;s purpose changes. It is stable precisely because it describes what something <em>is<\/em>.<\/p>\n<p><strong>Layer<\/strong> is what the validator computes: each node&#8217;s longest distance from the set of App roots, calculated as a topological-order pass over the graph. Layer numbers are not written anywhere and therefore layers cannot be broken. The concept doesn&#8217;t exist in code.<\/p>\n<p>As a consequence, the following observations arise:<\/p>\n<ol>\n<li><strong>No two components in the same computed layer can depend on each other.<\/strong> Same-layer dependencies are impossible by construction as they would contradict the longest-path definition.<\/li>\n<li><strong>Adding a legal dependency re-layers the graph without violating any rule.<\/strong> Say <code>App<\/code> depends directly on both <code>AppUpdate<\/code> and <code>DateFormatting<\/code>, placing both at L1. If <code>AppUpdate<\/code> later adds a dependency on <code>DateFormatting<\/code> \u2014 a legal Feature \u2192 Foundation edge \u2014 <code>DateFormatting<\/code> is simply recomputed to L2. Its longest path is now <code>App \u2192 AppUpdate \u2192 DateFormatting<\/code>. Nothing is violated; the graph just gets one step deeper.<\/li>\n<\/ol>\n<p><!--kg-card-begin: html--><\/p>\n<pre class=\"mermaid\">\nflowchart TB\n    subgraph L0[\"L0\"]\n        App\n    end\n    subgraph L1[\"L1\"]\n        AppUpdate\n    end\n    subgraph L2[\"L2\"]\n        DateFormatting\n    end\n    App --&gt; AppUpdate\n    App --&gt; DateFormatting\n    AppUpdate --&gt; DateFormatting\n    linkStyle 0 stroke:blue\n    linkStyle 1 stroke:green\n    linkStyle 2 stroke:orange\n<\/pre>\n<p><!--kg-card-end: html--><\/p>\n<p>This matters in practice because it means the question &#8220;which layer is my module at?&#8221; has no single, stable answer \u2014 it depends on the current state of the graph. The right question is always &#8220;which category is my module?&#8221; and the layer follows from the rules, automatically.<\/p>\n<hr>\n<h2 id=\"how-it-fits-together-in-practice\">How it fits together in practice<\/h2>\n<p>Each module carries a YAML spec declaring its category and its dependencies:<\/p>\n<pre><code class=\"language-yaml\">name: CountdownTimer\ncategory: foundation\nlocalDependencies: []\nremoteDependencies:\n  - name: PIE<\/code><\/pre>\n<pre><code class=\"language-yaml\">name: Checkout\ncategory: feature\nlocalDependencies:\n  - name: CountdownTimer\n    path: ..\/CountdownTimer\n  - name: DateFormatting\n    path: ..\/DateFormatting\n  - name: ErrorUtilities\n    path: ..\/ErrorUtilities\nremoteDependencies:\n  - name: PIE<\/code><\/pre>\n<p>A separate CLI (<a href=\"https:\/\/github.com\/justeattakeaway\/PackageGenerator?ref=albertodebortoli.com\">PackageGenerator<\/a>) converts these specs into SPM <code>Package.swift<\/code> manifests. App-level dependencies are declared in <code>TargetDependencies.json<\/code> files which are read by Tuist to generate the Xcode project. Third-party package categories live in the package catalogue (<code>PackageDependencies.json<\/code>). This is the only place where the SDK\/Utility distinction is declared, and the validator enforces it with the same rules as local modules. <\/p>\n<p>The validator (<code>ModularArchitectureValidator<\/code>) is a Swift CLI tool that pulls all three sources together, builds the full dependency graph, and runs the rules over it:<\/p>\n<pre><code class=\"language-bash\">ModularArchitectureValidator validate \n  --modules-folder Modules \n  --package-dependencies PackageDependencies.json \n  --target-dependencies TargetDependencies.json<\/code><\/pre>\n<p>On a rule violation, it reports every offending edge and exits with a non-zero code:<\/p>\n<pre><code class=\"language-bash\">ERROR: Checkout (feature) \u2192 Orders (feature) \u2014 feature cannot depend on feature\nERROR: APIClient (foundation) \u2192 Firebase (sdk) \u2014 foundation cannot depend on sdk<\/code><\/pre>\n<p>The validator runs locally during project setup and on every pull request on the CI. A violation blocks the PR. Is also exposes an <code>emit-graph<\/code> command that outputs the full graph in Mermaid or Graphviz DOT format which we find useful for visualising the dependency topology as the codebase evolves.<\/p>\n<hr>\n<h2 id=\"a-note-on-the-diamond-shape\">A note on the diamond shape<\/h2>\n<p>PIE is a leaf that many modules share. Several features and Foundation modules converge on it:<\/p>\n<p><!--kg-card-begin: html--><\/p>\n<pre class=\"mermaid\">\nflowchart TB\n    App --&gt; Search\n    App --&gt; Restaurants\n    App --&gt; Orders\n    App --&gt; ...\n    Search --&gt; PIE\n    Restaurants --&gt; PIE\n    Orders --&gt; PIE\n    ... --&gt; PIE\n<\/pre>\n<p><!--kg-card-end: html--><\/p>\n<p>This is a diamond shape in the graph, and it is entirely deliberate. &#8220;Dependency hell&#8221; describes conflicting <em>versions<\/em> of a shared dependency; for source-integrated first-party packages, there are no versions to conflict. A diamond over a stable, widely-shared Foundation module is healthy reuse.<\/p>\n<p>We accept that the Dependency Inversion Principle cannot be applied to a design library in any practical sense as it&#8217;s not feasible to abstract the entire design system behind protocols and that is the right call. PIE is a stable leaf that any Feature or Foundation may depend on.<\/p>\n<p>It is also worth noting that Apple has made the build-time cost of wide diamond dependencies substantially smaller in recent Xcode releases. With explicit module builds (<code>SWIFT_ENABLE_EXPLICIT_MODULES<\/code>), Xcode determines the full module graph upfront and begins compiling dependencies as soon as their emit-module phase completes, rather than waiting for the full compilation of each target. The diamond topology that looked concerning from a build-time perspective in 2019 is much less of an issue these days.<\/p>\n<hr>\n<h2 id=\"onwards-and-upwards\">Onwards and upwards<\/h2>\n<p>All in all, the 2026 refresh is narrower in scope than it might appear. The graph looks similar to what it looked like six years ago. The Facade pattern, the no-Feature \u2192 Feature rule, the monorepo, the reliance on demo apps remain unchanged.<\/p>\n<p>What changed is the vocabulary and the scope of enforcement. &#8220;Category&#8221; is now the authored, stable label for a component&#8217;s purpose; &#8220;layer&#8221; is reserved for the computed depth in the graph, which is a consequence of the rules rather than a property you configure. The Foundation category unified what was previously called &#8220;Core&#8221; and &#8220;Shared&#8221;, removing an ambiguity that had confused engineers. Third-party packages were brought inside the rules for the first time, giving us a formal way to enforce what was previously only a convention.<\/p>\n<p>What this unlocks is small but consequential. <code>APIClient<\/code> depending on <code>DateFormatting<\/code> is now an ordinary Foundation \u2192 Foundation edge, not a special case requiring explanation. New shared component like <code>CountdownTimer<\/code> are simply Foundation modules. A team proposing to add <code>Firebase<\/code> as a dependency of a Feature module will get a CI failure, not just a code review comment.<\/p>\n<p>Architectures rarely change in dramatic leaps. Most meaningful improvements are renamings, small relaxations, and rules written more precisely than before. We hope this one proves as durable as the last.<\/p>\n<\/div>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_1895\" class=\"pvc_stats total_only  \" data-element-id=\"1895\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" version=\"1.0\" viewBox=\"0 0 502 315\" preserveAspectRatio=\"xMidYMid meet\"><g transform=\"translate(0,332) scale(0.1,-0.1)\" fill=\"\" stroke=\"none\"><path d=\"M2394 3279 l-29 -30 -3 -207 c-2 -182 0 -211 15 -242 39 -76 157 -76 196 0 15 31 17 60 15 243 l-3 209 -33 29 c-26 23 -41 29 -80 29 -41 0 -53 -5 -78 -31z\"\/><path d=\"M3085 3251 c-45 -19 -58 -50 -96 -229 -47 -217 -49 -260 -13 -295 52 -53 146 -42 177 20 16 31 87 366 87 410 0 70 -86 122 -155 94z\"\/><path d=\"M1751 3234 c-13 -9 -29 -31 -37 -50 -12 -29 -10 -49 21 -204 19 -94 39 -189 45 -210 14 -50 54 -80 110 -80 34 0 48 6 76 34 21 21 34 44 34 59 0 14 -18 113 -40 219 -37 178 -43 195 -70 221 -36 32 -101 37 -139 11z\"\/><path d=\"M1163 3073 c-36 -7 -73 -59 -73 -102 0 -56 133 -378 171 -413 34 -32 83 -37 129 -13 70 36 67 87 -16 290 -86 209 -89 214 -129 231 -35 14 -42 15 -82 7z\"\/><path d=\"M3689 3066 c-15 -9 -33 -30 -42 -48 -48 -103 -147 -355 -147 -375 0 -98 131 -148 192 -74 13 15 57 108 97 206 80 196 84 226 37 273 -30 30 -99 39 -137 18z\"\/><path d=\"M583 2784 c-38 -19 -67 -74 -58 -113 9 -42 211 -354 242 -373 16 -10 45 -18 66 -18 51 0 107 52 107 100 0 39 -1 41 -124 234 -80 126 -108 162 -133 173 -41 17 -61 16 -100 -3z\"\/><path d=\"M4250 2784 c-14 -9 -74 -91 -133 -183 -95 -150 -107 -173 -107 -213 0 -55 33 -94 87 -104 67 -13 90 8 211 198 130 202 137 225 78 284 -27 27 -42 34 -72 34 -22 0 -50 -8 -64 -16z\"\/><path d=\"M2275 2693 c-553 -48 -1095 -270 -1585 -649 -135 -104 -459 -423 -483 -476 -23 -49 -22 -139 2 -186 73 -142 361 -457 571 -626 285 -228 642 -407 990 -497 242 -63 336 -73 660 -74 310 0 370 5 595 52 535 111 1045 392 1455 803 122 121 250 273 275 326 19 41 19 137 0 174 -41 79 -309 363 -465 492 -447 370 -946 591 -1479 653 -113 14 -422 18 -536 8z m395 -428 c171 -34 330 -124 456 -258 112 -119 167 -219 211 -378 27 -96 24 -300 -5 -401 -72 -255 -236 -447 -474 -557 -132 -62 -201 -76 -368 -76 -167 0 -236 14 -368 76 -213 98 -373 271 -451 485 -162 444 86 934 547 1084 153 49 292 57 452 25z m909 -232 c222 -123 408 -262 593 -441 76 -74 138 -139 138 -144 0 -16 -233 -242 -330 -319 -155 -123 -309 -223 -461 -299 l-81 -41 32 46 c18 26 49 83 70 128 143 306 141 649 -6 957 -25 52 -61 116 -79 142 l-34 47 45 -20 c26 -10 76 -36 113 -56z m-2057 25 c-40 -58 -105 -190 -130 -263 -110 -324 -59 -707 132 -981 25 -35 42 -64 37 -64 -19 0 -241 119 -326 174 -188 122 -406 314 -532 468 l-58 71 108 103 c185 178 428 349 672 473 66 33 121 60 123 61 2 0 -10 -19 -26 -42z\"\/><path d=\"M2375 1950 c-198 -44 -350 -190 -395 -379 -18 -76 -8 -221 19 -290 114 -284 457 -406 731 -260 98 52 188 154 231 260 27 69 37 214 19 290 -38 163 -166 304 -326 360 -67 23 -215 33 -279 19z\"\/><\/g><\/svg><\/i> <img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/i0.wp.com\/dev95.site\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif?resize=16%2C16&#038;ssl=1\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Originally published on the\u00a0Just Eat\u00a0Takeaway\u00a0Engineering Blog. When I published Modular iOS Architecture @ Just Eat in December 2019, modularisation was still a relatively novel concept in iOS development. We had been at it since 2016, driven by specific organisational needs:<\/p>\n<div class=\"hosteria-entry-more\"><a href=\"https:\/\/dev95.site\/ar\/revisiting-the-jet-ios-modular-architecture-in-2026\/\" class=\"no-underline font-light  group-hover:text-primary-800 dark:group-hover:text-primary-300 py-1\">Read more &gt;&gt;&gt;<\/a><\/div>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_1895\" class=\"pvc_stats total_only\" data-element-id=\"1895\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" version=\"1.0\" viewbox=\"0 0 502 315\" preserveaspectratio=\"xMidYMid meet\"><g transform=\"translate(0,332) scale(0.1,-0.1)\" fill=\"\" stroke=\"none\"><path d=\"M2394 3279 l-29 -30 -3 -207 c-2 -182 0 -211 15 -242 39 -76 157 -76 196 0 15 31 17 60 15 243 l-3 209 -33 29 c-26 23 -41 29 -80 29 -41 0 -53 -5 -78 -31z\"\/><path d=\"M3085 3251 c-45 -19 -58 -50 -96 -229 -47 -217 -49 -260 -13 -295 52 -53 146 -42 177 20 16 31 87 366 87 410 0 70 -86 122 -155 94z\"\/><path d=\"M1751 3234 c-13 -9 -29 -31 -37 -50 -12 -29 -10 -49 21 -204 19 -94 39 -189 45 -210 14 -50 54 -80 110 -80 34 0 48 6 76 34 21 21 34 44 34 59 0 14 -18 113 -40 219 -37 178 -43 195 -70 221 -36 32 -101 37 -139 11z\"\/><path d=\"M1163 3073 c-36 -7 -73 -59 -73 -102 0 -56 133 -378 171 -413 34 -32 83 -37 129 -13 70 36 67 87 -16 290 -86 209 -89 214 -129 231 -35 14 -42 15 -82 7z\"\/><path d=\"M3689 3066 c-15 -9 -33 -30 -42 -48 -48 -103 -147 -355 -147 -375 0 -98 131 -148 192 -74 13 15 57 108 97 206 80 196 84 226 37 273 -30 30 -99 39 -137 18z\"\/><path d=\"M583 2784 c-38 -19 -67 -74 -58 -113 9 -42 211 -354 242 -373 16 -10 45 -18 66 -18 51 0 107 52 107 100 0 39 -1 41 -124 234 -80 126 -108 162 -133 173 -41 17 -61 16 -100 -3z\"\/><path d=\"M4250 2784 c-14 -9 -74 -91 -133 -183 -95 -150 -107 -173 -107 -213 0 -55 33 -94 87 -104 67 -13 90 8 211 198 130 202 137 225 78 284 -27 27 -42 34 -72 34 -22 0 -50 -8 -64 -16z\"\/><path d=\"M2275 2693 c-553 -48 -1095 -270 -1585 -649 -135 -104 -459 -423 -483 -476 -23 -49 -22 -139 2 -186 73 -142 361 -457 571 -626 285 -228 642 -407 990 -497 242 -63 336 -73 660 -74 310 0 370 5 595 52 535 111 1045 392 1455 803 122 121 250 273 275 326 19 41 19 137 0 174 -41 79 -309 363 -465 492 -447 370 -946 591 -1479 653 -113 14 -422 18 -536 8z m395 -428 c171 -34 330 -124 456 -258 112 -119 167 -219 211 -378 27 -96 24 -300 -5 -401 -72 -255 -236 -447 -474 -557 -132 -62 -201 -76 -368 -76 -167 0 -236 14 -368 76 -213 98 -373 271 -451 485 -162 444 86 934 547 1084 153 49 292 57 452 25z m909 -232 c222 -123 408 -262 593 -441 76 -74 138 -139 138 -144 0 -16 -233 -242 -330 -319 -155 -123 -309 -223 -461 -299 l-81 -41 32 46 c18 26 49 83 70 128 143 306 141 649 -6 957 -25 52 -61 116 -79 142 l-34 47 45 -20 c26 -10 76 -36 113 -56z m-2057 25 c-40 -58 -105 -190 -130 -263 -110 -324 -59 -707 132 -981 25 -35 42 -64 37 -64 -19 0 -241 119 -326 174 -188 122 -406 314 -532 468 l-58 71 108 103 c185 178 428 349 672 473 66 33 121 60 123 61 2 0 -10 -19 -26 -42z\"\/><path d=\"M2375 1950 c-198 -44 -350 -190 -395 -379 -18 -76 -8 -221 19 -290 114 -284 457 -406 731 -260 98 52 188 154 231 260 27 69 37 214 19 290 -38 163 -166 304 -326 360 -67 23 -215 33 -279 19z\"\/><\/g><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/dev95.site\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=\"0\" \/><\/p>\n<div class=\"pvc_clear\"><\/div>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"fp_fajr_begins":"","fp_fajr_iqamah":"","fp_dhuhr_begins":"","fp_dhuhr_iqamah":"","fp_asr_begins":"","fp_asr_iqamah":"","fp_maghrib_begins":"","fp_maghrib_iqamah":"","fp_isha_begins":"","fp_isha_iqamah":"","fp_midnight":"","fp_midnight_name":"","fp_sunrise":"","fp_single_prayer_begins_title":"","fp_single_prayer_iqamah_title":"","fp_prayer_times_for_today":"","fp_hijra_date":"","fp_fajr_name":"","fp_dhuhr_name":"","fp_asr_name":"","fp_maghrib_name":"","fp_isha_name":"","fp_sunrise_name":"","fp_currentDate":"","fp_current_time":"","fp_current_title":"","fp_current_location":"","fp_masjid_name":"","fp_prayer_title":"","fp_next_prayer_iqamah_time":"","fp_next_prayer_iqamah_title":"","fp_next_prayer_begins_time":"","fp_next_prayer_begins_title":"","fp_next_prayer_title":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[37],"tags":[],"class_list":["post-1895","post","type-post","status-publish","format-standard","hentry","category-posts"],"a3_pvc":{"activated":true,"total_views":0,"today_views":0},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Revisiting the JET iOS Modular Architecture in 2026 - Dev95<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/dev95.site\/ar\/revisiting-the-jet-ios-modular-architecture-in-2026\/\" \/>\n<meta property=\"og:locale\" content=\"ar_AR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Revisiting the JET iOS Modular Architecture in 2026 - Dev95\" \/>\n<meta property=\"og:description\" content=\"Originally published on the\u00a0Just Eat\u00a0Takeaway\u00a0Engineering Blog. When I published Modular iOS Architecture @ Just Eat in December 2019, modularisation was still a relatively novel concept in iOS development. We had been at it since 2016, driven by specific organisational needs:Read more &gt;&gt;&gt;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/dev95.site\/ar\/revisiting-the-jet-ios-modular-architecture-in-2026\/\" \/>\n<meta property=\"og:site_name\" content=\"Dev95\" \/>\n<meta property=\"article:published_time\" content=\"2026-07-15T18:48:07+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/storage.ghost.io\/c\/ae\/f4\/aef4d625-32a2-417b-86f4-22c70a9b47a1\/content\/images\/2026\/07\/modular_arch_2026.png\" \/>\n<meta name=\"author\" content=\"dev95\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u0643\u064f\u062a\u0628 \u0628\u0648\u0627\u0633\u0637\u0629\" \/>\n\t<meta name=\"twitter:data1\" content=\"dev95\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u0648\u0642\u062a \u0627\u0644\u0642\u0631\u0627\u0621\u0629 \u0627\u0644\u0645\u064f\u0642\u062f\u0651\u0631\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 \u062f\u0642\u064a\u0642\u0629\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/dev95.site\\\/revisiting-the-jet-ios-modular-architecture-in-2026\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/revisiting-the-jet-ios-modular-architecture-in-2026\\\/\"},\"author\":{\"name\":\"dev95\",\"@id\":\"https:\\\/\\\/dev95.site\\\/#\\\/schema\\\/person\\\/b807805ffe2916206b04d0938bce0298\"},\"headline\":\"Revisiting the JET iOS Modular Architecture in 2026\",\"datePublished\":\"2026-07-15T18:48:07+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/revisiting-the-jet-ios-modular-architecture-in-2026\\\/\"},\"wordCount\":2406,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/revisiting-the-jet-ios-modular-architecture-in-2026\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/storage.ghost.io\\\/c\\\/ae\\\/f4\\\/aef4d625-32a2-417b-86f4-22c70a9b47a1\\\/content\\\/images\\\/2026\\\/07\\\/modular_arch_2026.png\",\"articleSection\":[\"Posts\"],\"inLanguage\":\"ar\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/dev95.site\\\/revisiting-the-jet-ios-modular-architecture-in-2026\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/dev95.site\\\/revisiting-the-jet-ios-modular-architecture-in-2026\\\/\",\"url\":\"https:\\\/\\\/dev95.site\\\/revisiting-the-jet-ios-modular-architecture-in-2026\\\/\",\"name\":\"Revisiting the JET iOS Modular Architecture in 2026 - Dev95\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/revisiting-the-jet-ios-modular-architecture-in-2026\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/revisiting-the-jet-ios-modular-architecture-in-2026\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/storage.ghost.io\\\/c\\\/ae\\\/f4\\\/aef4d625-32a2-417b-86f4-22c70a9b47a1\\\/content\\\/images\\\/2026\\\/07\\\/modular_arch_2026.png\",\"datePublished\":\"2026-07-15T18:48:07+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/revisiting-the-jet-ios-modular-architecture-in-2026\\\/#breadcrumb\"},\"inLanguage\":\"ar\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/dev95.site\\\/revisiting-the-jet-ios-modular-architecture-in-2026\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ar\",\"@id\":\"https:\\\/\\\/dev95.site\\\/revisiting-the-jet-ios-modular-architecture-in-2026\\\/#primaryimage\",\"url\":\"https:\\\/\\\/storage.ghost.io\\\/c\\\/ae\\\/f4\\\/aef4d625-32a2-417b-86f4-22c70a9b47a1\\\/content\\\/images\\\/2026\\\/07\\\/modular_arch_2026.png\",\"contentUrl\":\"https:\\\/\\\/storage.ghost.io\\\/c\\\/ae\\\/f4\\\/aef4d625-32a2-417b-86f4-22c70a9b47a1\\\/content\\\/images\\\/2026\\\/07\\\/modular_arch_2026.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/dev95.site\\\/revisiting-the-jet-ios-modular-architecture-in-2026\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/dev95.site\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Revisiting the JET iOS Modular Architecture in 2026\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/dev95.site\\\/#website\",\"url\":\"https:\\\/\\\/dev95.site\\\/\",\"name\":\"Dev95\",\"description\":\"A comprehensive platform for data and knowledge, delivering reliable content that meets the aspirations of readers and enthusiasts.\",\"publisher\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/dev95.site\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ar\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/dev95.site\\\/#organization\",\"name\":\"Dev95\",\"url\":\"https:\\\/\\\/dev95.site\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ar\",\"@id\":\"https:\\\/\\\/dev95.site\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/dev95.site\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/rbrrbr-6.png?fit=512%2C512&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/dev95.site\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/rbrrbr-6.png?fit=512%2C512&ssl=1\",\"width\":512,\"height\":512,\"caption\":\"Dev95\"},\"image\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/dev95.site\\\/#\\\/schema\\\/person\\\/b807805ffe2916206b04d0938bce0298\",\"name\":\"dev95\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ar\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a70a73d950838b20cd80d7ebdc955737e802e8cd896044c5473b32b946c0662a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a70a73d950838b20cd80d7ebdc955737e802e8cd896044c5473b32b946c0662a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a70a73d950838b20cd80d7ebdc955737e802e8cd896044c5473b32b946c0662a?s=96&d=mm&r=g\",\"caption\":\"dev95\"},\"url\":\"https:\\\/\\\/dev95.site\\\/ar\\\/author\\\/mohammad\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Revisiting the JET iOS Modular Architecture in 2026 - Dev95","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/dev95.site\/ar\/revisiting-the-jet-ios-modular-architecture-in-2026\/","og_locale":"ar_AR","og_type":"article","og_title":"Revisiting the JET iOS Modular Architecture in 2026 - Dev95","og_description":"Originally published on the\u00a0Just Eat\u00a0Takeaway\u00a0Engineering Blog. When I published Modular iOS Architecture @ Just Eat in December 2019, modularisation was still a relatively novel concept in iOS development. We had been at it since 2016, driven by specific organisational needs:Read more &gt;&gt;&gt;","og_url":"https:\/\/dev95.site\/ar\/revisiting-the-jet-ios-modular-architecture-in-2026\/","og_site_name":"Dev95","article_published_time":"2026-07-15T18:48:07+00:00","og_image":[{"url":"https:\/\/storage.ghost.io\/c\/ae\/f4\/aef4d625-32a2-417b-86f4-22c70a9b47a1\/content\/images\/2026\/07\/modular_arch_2026.png","type":"","width":"","height":""}],"author":"dev95","twitter_card":"summary_large_image","twitter_misc":{"\u0643\u064f\u062a\u0628 \u0628\u0648\u0627\u0633\u0637\u0629":"dev95","\u0648\u0642\u062a \u0627\u0644\u0642\u0631\u0627\u0621\u0629 \u0627\u0644\u0645\u064f\u0642\u062f\u0651\u0631":"13 \u062f\u0642\u064a\u0642\u0629"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/dev95.site\/revisiting-the-jet-ios-modular-architecture-in-2026\/#article","isPartOf":{"@id":"https:\/\/dev95.site\/revisiting-the-jet-ios-modular-architecture-in-2026\/"},"author":{"name":"dev95","@id":"https:\/\/dev95.site\/#\/schema\/person\/b807805ffe2916206b04d0938bce0298"},"headline":"Revisiting the JET iOS Modular Architecture in 2026","datePublished":"2026-07-15T18:48:07+00:00","mainEntityOfPage":{"@id":"https:\/\/dev95.site\/revisiting-the-jet-ios-modular-architecture-in-2026\/"},"wordCount":2406,"commentCount":0,"publisher":{"@id":"https:\/\/dev95.site\/#organization"},"image":{"@id":"https:\/\/dev95.site\/revisiting-the-jet-ios-modular-architecture-in-2026\/#primaryimage"},"thumbnailUrl":"https:\/\/storage.ghost.io\/c\/ae\/f4\/aef4d625-32a2-417b-86f4-22c70a9b47a1\/content\/images\/2026\/07\/modular_arch_2026.png","articleSection":["Posts"],"inLanguage":"ar","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/dev95.site\/revisiting-the-jet-ios-modular-architecture-in-2026\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/dev95.site\/revisiting-the-jet-ios-modular-architecture-in-2026\/","url":"https:\/\/dev95.site\/revisiting-the-jet-ios-modular-architecture-in-2026\/","name":"Revisiting the JET iOS Modular Architecture in 2026 - Dev95","isPartOf":{"@id":"https:\/\/dev95.site\/#website"},"primaryImageOfPage":{"@id":"https:\/\/dev95.site\/revisiting-the-jet-ios-modular-architecture-in-2026\/#primaryimage"},"image":{"@id":"https:\/\/dev95.site\/revisiting-the-jet-ios-modular-architecture-in-2026\/#primaryimage"},"thumbnailUrl":"https:\/\/storage.ghost.io\/c\/ae\/f4\/aef4d625-32a2-417b-86f4-22c70a9b47a1\/content\/images\/2026\/07\/modular_arch_2026.png","datePublished":"2026-07-15T18:48:07+00:00","breadcrumb":{"@id":"https:\/\/dev95.site\/revisiting-the-jet-ios-modular-architecture-in-2026\/#breadcrumb"},"inLanguage":"ar","potentialAction":[{"@type":"ReadAction","target":["https:\/\/dev95.site\/revisiting-the-jet-ios-modular-architecture-in-2026\/"]}]},{"@type":"ImageObject","inLanguage":"ar","@id":"https:\/\/dev95.site\/revisiting-the-jet-ios-modular-architecture-in-2026\/#primaryimage","url":"https:\/\/storage.ghost.io\/c\/ae\/f4\/aef4d625-32a2-417b-86f4-22c70a9b47a1\/content\/images\/2026\/07\/modular_arch_2026.png","contentUrl":"https:\/\/storage.ghost.io\/c\/ae\/f4\/aef4d625-32a2-417b-86f4-22c70a9b47a1\/content\/images\/2026\/07\/modular_arch_2026.png"},{"@type":"BreadcrumbList","@id":"https:\/\/dev95.site\/revisiting-the-jet-ios-modular-architecture-in-2026\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/dev95.site\/"},{"@type":"ListItem","position":2,"name":"Revisiting the JET iOS Modular Architecture in 2026"}]},{"@type":"WebSite","@id":"https:\/\/dev95.site\/#website","url":"https:\/\/dev95.site\/","name":"Dev95","description":"A comprehensive platform for data and knowledge, delivering reliable content that meets the aspirations of readers and enthusiasts.","publisher":{"@id":"https:\/\/dev95.site\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/dev95.site\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ar"},{"@type":"Organization","@id":"https:\/\/dev95.site\/#organization","name":"Dev95","url":"https:\/\/dev95.site\/","logo":{"@type":"ImageObject","inLanguage":"ar","@id":"https:\/\/dev95.site\/#\/schema\/logo\/image\/","url":"https:\/\/i0.wp.com\/dev95.site\/wp-content\/uploads\/2026\/07\/rbrrbr-6.png?fit=512%2C512&ssl=1","contentUrl":"https:\/\/i0.wp.com\/dev95.site\/wp-content\/uploads\/2026\/07\/rbrrbr-6.png?fit=512%2C512&ssl=1","width":512,"height":512,"caption":"Dev95"},"image":{"@id":"https:\/\/dev95.site\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/dev95.site\/#\/schema\/person\/b807805ffe2916206b04d0938bce0298","name":"dev95","image":{"@type":"ImageObject","inLanguage":"ar","@id":"https:\/\/secure.gravatar.com\/avatar\/a70a73d950838b20cd80d7ebdc955737e802e8cd896044c5473b32b946c0662a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/a70a73d950838b20cd80d7ebdc955737e802e8cd896044c5473b32b946c0662a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a70a73d950838b20cd80d7ebdc955737e802e8cd896044c5473b32b946c0662a?s=96&d=mm&r=g","caption":"dev95"},"url":"https:\/\/dev95.site\/ar\/author\/mohammad\/"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/posts\/1895","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/comments?post=1895"}],"version-history":[{"count":0,"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/posts\/1895\/revisions"}],"wp:attachment":[{"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/media?parent=1895"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/categories?post=1895"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/tags?post=1895"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}