<?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: KCL Tech</title>
    <description>The latest articles on DEV Community by KCL Tech (@kcltech).</description>
    <link>https://dev.to/kcltech</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%2F4010658%2Fbac64b41-16c4-44d7-9991-a563b367997b.png</url>
      <title>DEV Community: KCL Tech</title>
      <link>https://dev.to/kcltech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kcltech"/>
    <language>en</language>
    <item>
      <title>How Monorepos Work: A beginner-friendly guide to monorepos</title>
      <dc:creator>KCL Tech</dc:creator>
      <pubDate>Sat, 15 Aug 2026 17:08:08 +0000</pubDate>
      <link>https://dev.to/kcltech/how-monorepos-work-a-beginner-friendly-guide-to-monorepos-400g</link>
      <guid>https://dev.to/kcltech/how-monorepos-work-a-beginner-friendly-guide-to-monorepos-400g</guid>
      <description>&lt;p&gt;&lt;em&gt;Written by Waseef Khan, Co-President of KCL Tech.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A codebase rarely stays as one application forever.&lt;/p&gt;

&lt;p&gt;Imagine a team building a public marketing site, an internal admin platform and a customer-facing learning platform. Each product has its own users and responsibilities, but they share the same organisation, visual language, authentication patterns and engineering team.&lt;/p&gt;

&lt;p&gt;That creates a structural question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Should every product live in its own repository, or should they live together?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A monorepo can be the most useful answer.&lt;/p&gt;

&lt;p&gt;KCL Tech is committed to making technology accessible, so this guide assumes no previous experience with monorepos. I will explain the basic language first, then show how the tools fit together. We will also explore how the same structure can make a codebase easier for AI coding agents to navigate safely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five terms to know before we begin
&lt;/h2&gt;

&lt;p&gt;You only need a few ideas to follow the rest of this guide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repository:&lt;/strong&gt; A project folder tracked by a version-control tool such as Git. It contains the code and a history of changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application:&lt;/strong&gt; A product people can use, such as a website, mobile app or admin dashboard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Package:&lt;/strong&gt; A reusable collection of code. One package might provide buttons, while another handles authentication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency:&lt;/strong&gt; Code that another piece of code relies on. If an app uses a button package, the button package is one of its dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build:&lt;/strong&gt; The process of turning source code into a version that can be tested or deployed for people to use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If those terms make sense, you already have enough context to understand a monorepo. If Git or package managers are completely new to you, &lt;a href="https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F" rel="noopener noreferrer"&gt;the Pro Git introduction&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Client-side_tools/Package_management" rel="noopener noreferrer"&gt;MDN's package-management basics&lt;/a&gt; are friendly starting points.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a monorepo?
&lt;/h2&gt;

&lt;p&gt;A monorepo is one repository containing multiple applications or packages.&lt;/p&gt;

&lt;p&gt;Think of it as one building with several rooms. Each application has its own room and purpose, while shared facilities sit in the same building. The rooms do not become one giant room simply because they share an address.&lt;/p&gt;

&lt;p&gt;It is not necessarily one application, one deployment or one giant bundle. A monorepo can contain several independently deployed products:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;platform/
├── apps/
│   ├── marketing/
│   ├── admin/
│   └── learning/
├── packages/
│   ├── ui/
│   ├── auth/
│   ├── database/
│   ├── eslint-config/
│   └── typescript-config/
├── design/
├── package.json
├── pnpm-workspace.yaml
└── turbo.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;apps/marketing&lt;/code&gt; is the public website.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;apps/admin&lt;/code&gt; is the internal platform used to manage content, events and programmes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;apps/learning&lt;/code&gt; is the customer-facing learning platform.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;packages/ui&lt;/code&gt; contains reusable interface primitives.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;packages/auth&lt;/code&gt; contains shared authentication logic and types.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;design&lt;/code&gt; documents how the product family should feel: visual direction, motion, interaction principles, accessibility and content style.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The applications remain separate products. They can have different users, web addresses and release schedules. The repository simply gives their code a shared home.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the pieces are connected
&lt;/h2&gt;

&lt;p&gt;The folder tree shows us where the code lives. A &lt;strong&gt;dependency graph&lt;/strong&gt; shows us which parts rely on other parts.&lt;/p&gt;

&lt;p&gt;Imagine the following relationships:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;marketing ──┐
admin ──────┼──&amp;gt; ui
learning ───┘

admin ──────┐
learning ───┼──&amp;gt; auth ──&amp;gt; database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In technical language, each application or package is a &lt;strong&gt;node&lt;/strong&gt;, and each connection is an &lt;strong&gt;edge&lt;/strong&gt;. In plain English, each box is a piece of the system and each arrow means “uses”.&lt;/p&gt;

&lt;p&gt;This matters because the graph tells our tooling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what must be built first;&lt;/li&gt;
&lt;li&gt;which products may be affected by a change;&lt;/li&gt;
&lt;li&gt;which tests need to run;&lt;/li&gt;
&lt;li&gt;which previous outputs can be reused from a cache;&lt;/li&gt;
&lt;li&gt;how many places might be affected by a shared change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tools such as Turborepo and Nx use these relationships to decide what work is necessary. The tools differ, but the underlying idea is simple: understand what depends on what before running commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  How workspace packages connect
&lt;/h2&gt;

&lt;p&gt;We now need a way to tell our package manager which folders belong to the same workspace. A &lt;strong&gt;package manager&lt;/strong&gt; installs dependencies and runs project commands. In this example, we use pnpm.&lt;/p&gt;

&lt;p&gt;The root workspace file lists the directories that belong to the monorepo:&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="c1"&gt;# pnpm-workspace.yaml&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;apps/*"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;packages/*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each project still has its own &lt;code&gt;package.json&lt;/code&gt;, which acts like an identity card and instruction sheet for that project. An application can list another package from the same repository as a dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@platform/learning"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@platform/ui"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workspace:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@platform/auth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workspace:*"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;workspace:*&lt;/code&gt; value tells pnpm to use the local package from this repository. We do not need to publish &lt;code&gt;@platform/ui&lt;/code&gt; publicly just to use it in the learning app.&lt;/p&gt;

&lt;p&gt;The result is a clean import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@platform/ui/button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of a fragile relative path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../../../packages/ui/src/button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first version clearly says, “this app uses the shared UI package”. The second reaches through several folders and makes that relationship harder to understand or control.&lt;/p&gt;

&lt;h2&gt;
  
  
  How commands run in the correct order
&lt;/h2&gt;

&lt;p&gt;A dependency graph describes which projects rely on each other. A &lt;strong&gt;task graph&lt;/strong&gt; describes the order in which commands such as build, test and lint should run. Linting is an automated check for code-quality and style problems.&lt;/p&gt;

&lt;p&gt;For example, the learning app cannot complete its production build until the internal packages it consumes are ready. A minimal Turborepo configuration can encode that relationship:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://turborepo.com/schema.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dependsOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"^build"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"outputs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;".next/**"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"!.next/cache/**"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist/**"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dependsOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"^lint"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typecheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dependsOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"^typecheck"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dependsOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"^build"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"outputs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"coverage/**"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"cache"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"persistent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You do not need to understand every line yet. The important one is &lt;code&gt;^build&lt;/code&gt;, which means: build this package's dependencies before building the package itself.&lt;/p&gt;

&lt;p&gt;The root &lt;code&gt;package.json&lt;/code&gt; then becomes a simple front door to the entire repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"turbo dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"turbo build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"turbo lint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typecheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"turbo typecheck"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"turbo test"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can run everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or focus on one product:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm &lt;span class="nt"&gt;--filter&lt;/span&gt; @platform/learning dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;strong&gt;task runner&lt;/strong&gt; such as Turborepo reads this configuration. It can run unrelated work at the same time, respect the correct order and reuse previous results through a cache. A cache is simply stored work that does not need to be repeated when nothing relevant has changed.&lt;/p&gt;

&lt;p&gt;That is what prevents a growing monorepo from automatically becoming a slow monorepo. To go further, Turborepo's guides explain &lt;a href="https://turborepo.com/docs/core-concepts/internal-packages" rel="noopener noreferrer"&gt;internal packages&lt;/a&gt; and &lt;a href="https://turborepo.com/docs/core-concepts/package-and-task-graph" rel="noopener noreferrer"&gt;package and task graphs&lt;/a&gt; in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  What belongs in a shared package?
&lt;/h2&gt;

&lt;p&gt;The easiest monorepo mistake is sharing code simply because two files look similar.&lt;/p&gt;

&lt;p&gt;Good shared packages usually represent stable capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;design-system primitives such as buttons, inputs and dialogs;&lt;/li&gt;
&lt;li&gt;authentication clients, session types and permission helpers;&lt;/li&gt;
&lt;li&gt;database schemas and generated types;&lt;/li&gt;
&lt;li&gt;analytics wrappers;&lt;/li&gt;
&lt;li&gt;linting, formatting and TypeScript configuration;&lt;/li&gt;
&lt;li&gt;utilities with the same meaning across every application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code should normally remain inside an application when it represents that product's domain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a learning-platform lesson timeline;&lt;/li&gt;
&lt;li&gt;an admin moderation queue;&lt;/li&gt;
&lt;li&gt;marketing-page campaign sections;&lt;/li&gt;
&lt;li&gt;a workflow that merely happens to resemble another workflow today.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A useful rule is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Share stable capability, not accidental similarity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sharing too early can create an overcomplicated component with too many options, unclear ownership and several products afraid to change it. A small amount of duplication can be safer until the correct shared solution becomes obvious.&lt;/p&gt;

&lt;h2&gt;
  
  
  One design language does not mean one interface
&lt;/h2&gt;

&lt;p&gt;A shared UI package should contain implementation. The &lt;code&gt;design&lt;/code&gt; directory should explain intent.&lt;/p&gt;

&lt;p&gt;For a multi-product repository, that directory can stay deliberately simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;design/
├── README.md
├── foundations.md
├── components.md
├── motion.md
├── accessibility.md
└── content.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It answers questions that code alone cannot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Should the product feel editorial, playful, technical or institutional?&lt;/li&gt;
&lt;li&gt;When should motion communicate state, and when would it become decoration?&lt;/li&gt;
&lt;li&gt;How dense should the admin platform feel compared with the marketing site?&lt;/li&gt;
&lt;li&gt;Which behaviours must remain consistent across all three products?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The products can feel related without looking cloned. Marketing may be expressive, Learning may be encouraging and progress-led, and Admin may prioritise density and speed. Shared foundations should create family resemblance, not forced uniformity.&lt;/p&gt;

&lt;h2&gt;
  
  
  A change moving through the monorepo
&lt;/h2&gt;

&lt;p&gt;Suppose we add a new &lt;code&gt;Avatar&lt;/code&gt; component to &lt;code&gt;@platform/ui&lt;/code&gt; and use it in the learning app.&lt;/p&gt;

&lt;p&gt;The flow looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add the component and its tests inside &lt;code&gt;packages/ui&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Export it through the package's public API, meaning the approved way other projects can access it.&lt;/li&gt;
&lt;li&gt;Import it inside &lt;code&gt;apps/learning&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run code-quality checks, type checks and tests for the projects that could be affected.&lt;/li&gt;
&lt;li&gt;Build the learning app and any other consumer affected by the shared package change.&lt;/li&gt;
&lt;li&gt;Deploy the learning app independently.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The shared component and the app using it can be reviewed together in one proposed change, often called a pull request. The products can still be released independently: changing Learning does not require deploying Marketing or Admin unless they are genuinely affected.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an agentic monorepo?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;coding agent&lt;/strong&gt; is an AI system that can do more than suggest a line of code. Depending on the tool and the permissions it receives, it may be able to inspect files, edit code, run commands and check its own work.&lt;/p&gt;

&lt;p&gt;“Agentic monorepo” is not a separate build tool or formal repository type. I use it to describe a monorepo deliberately designed so coding agents can understand it, make limited and relevant changes, and verify their own work.&lt;/p&gt;

&lt;p&gt;An ordinary monorepo gives an agent access to a lot of code. An agentic monorepo gives it a map, boundaries and a safe route through that code.&lt;/p&gt;

&lt;p&gt;That distinction matters. The biggest advantage of a monorepo for an agent is context: the applications, rules, design system and tests are available together. Its biggest risk is also context: an agent working without clear limits could change a shared package and unintentionally affect every application.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Give the repository a clear map
&lt;/h3&gt;

&lt;p&gt;Create a root instruction file that explains the repository in plain language. Some coding tools read files such as &lt;code&gt;AGENTS.md&lt;/code&gt; automatically. The exact filename is less important than the principle: important repository knowledge should live beside the code instead of only in someone's head.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Repository engineering guide&lt;/span&gt;

&lt;span class="gu"&gt;## Repository map&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; apps/marketing: public website
&lt;span class="p"&gt;-&lt;/span&gt; apps/admin: internal operations platform
&lt;span class="p"&gt;-&lt;/span&gt; apps/learning: customer learning platform
&lt;span class="p"&gt;-&lt;/span&gt; packages/ui: shared interface primitives only
&lt;span class="p"&gt;-&lt;/span&gt; packages/auth: authentication and authorisation contracts
&lt;span class="p"&gt;-&lt;/span&gt; design: product-wide design principles

&lt;span class="gu"&gt;## Commands&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Install: pnpm install
&lt;span class="p"&gt;-&lt;/span&gt; Run Learning: pnpm --filter @platform/learning dev
&lt;span class="p"&gt;-&lt;/span&gt; Validate affected work: pnpm lint &amp;amp;&amp;amp; pnpm typecheck &amp;amp;&amp;amp; pnpm test

&lt;span class="gu"&gt;## Rules&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Do not import directly between apps.
&lt;span class="p"&gt;-&lt;/span&gt; Consume shared code through package public APIs.
&lt;span class="p"&gt;-&lt;/span&gt; Do not place product-specific workflows in packages/ui.
&lt;span class="p"&gt;-&lt;/span&gt; Never commit secrets or real customer data.
&lt;span class="p"&gt;-&lt;/span&gt; Update tests when behaviour changes.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This avoids forcing an agent to infer critical architecture from thousands of files.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Scope instructions to the work
&lt;/h3&gt;

&lt;p&gt;Root guidance should be short and universal. Product-specific knowledge should live closer to the product:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AGENTS.md
apps/
├── admin/
│   └── AGENTS.md
└── learning/
    └── AGENTS.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Learning instructions might explain enrolment rules and customer privacy. The Admin instructions might explain role permissions and audit logging. This keeps the information given to the agent relevant instead of loading every rule for every task.&lt;/p&gt;

&lt;p&gt;Agent products support different instruction filenames and scoping rules, so check the tool you use. The architectural principle remains portable: global rules at the root, local rules near the code they govern.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Make the correct action the easy action
&lt;/h3&gt;

&lt;p&gt;An agent should not need to invent the setup process or assemble a validation command.&lt;/p&gt;

&lt;p&gt;Prefer predictable entry points:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm &lt;span class="nb"&gt;install
&lt;/span&gt;pnpm &lt;span class="nt"&gt;--filter&lt;/span&gt; @platform/learning dev
pnpm &lt;span class="nt"&gt;--filter&lt;/span&gt; @platform/learning &lt;span class="nb"&gt;test
&lt;/span&gt;pnpm &lt;span class="nt"&gt;--filter&lt;/span&gt; @platform/learning typecheck
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.env.example&lt;/code&gt; files containing names, never secrets;&lt;/li&gt;
&lt;li&gt;predictable sample data containing no personal information;&lt;/li&gt;
&lt;li&gt;scripts that work without interactive prompts;&lt;/li&gt;
&lt;li&gt;clear package names and ownership;&lt;/li&gt;
&lt;li&gt;one command for formatting and one command for validation;&lt;/li&gt;
&lt;li&gt;fast unit tests plus focused end-to-end tests for critical journeys.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agents become more reliable when the feedback loop is short enough to run after every meaningful change.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Encode boundaries in tools, not only prose
&lt;/h3&gt;

&lt;p&gt;Instructions can be ignored or misunderstood. Architectural rules should also be enforced mechanically.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;automated code rules that forbid imports from one app into another;&lt;/li&gt;
&lt;li&gt;TypeScript project references and package exports;&lt;/li&gt;
&lt;li&gt;required human reviewers for sensitive packages;&lt;/li&gt;
&lt;li&gt;schema validation at API boundaries;&lt;/li&gt;
&lt;li&gt;protected automated checks before changes can be merged;&lt;/li&gt;
&lt;li&gt;permission tests for Admin and Learning;&lt;/li&gt;
&lt;li&gt;secret scanning and dependency auditing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An instruction saying “do not bypass the authentication package” is helpful. An automated rule and a failing test are stronger because they actively stop an unsafe change.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Optimise for selective context
&lt;/h3&gt;

&lt;p&gt;More context is not always better. An agent working on a Learning dashboard should not need the full Marketing application in its prompt.&lt;/p&gt;

&lt;p&gt;A well-structured monorepo allows the agent to inspect:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the root map;&lt;/li&gt;
&lt;li&gt;the target application's instructions;&lt;/li&gt;
&lt;li&gt;its direct package dependencies;&lt;/li&gt;
&lt;li&gt;relevant tests and design documentation;&lt;/li&gt;
&lt;li&gt;the affected task graph.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is one reason clear package boundaries matter beyond speed. They also define what humans and agents need to understand for a particular task.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Define the verification loop
&lt;/h3&gt;

&lt;p&gt;Every task given to an agent should end with evidence, not confidence.&lt;/p&gt;

&lt;p&gt;A sensible definition of done is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the requested behaviour is implemented;&lt;/li&gt;
&lt;li&gt;existing architectural boundaries remain intact;&lt;/li&gt;
&lt;li&gt;linting and type checks pass for affected projects;&lt;/li&gt;
&lt;li&gt;relevant tests pass;&lt;/li&gt;
&lt;li&gt;user-facing changes are visually inspected;&lt;/li&gt;
&lt;li&gt;migrations and environment changes are documented;&lt;/li&gt;
&lt;li&gt;the final summary names changed packages and remaining risks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent should be able to discover and run this loop from the repository itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical agent workflow
&lt;/h2&gt;

&lt;p&gt;For a task such as “add role-based progress editing to Learning”, an agent-ready workflow would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read root instructions
        ↓
Read Learning instructions
        ↓
Inspect Learning's dependency boundary
        ↓
Plan the smallest valid change
        ↓
Implement inside Learning where possible
        ↓
Run relevant code-quality checks, type checks and tests
        ↓
Review the affected graph and report evidence
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the work requires changing &lt;code&gt;packages/auth&lt;/code&gt;, the task expands deliberately because Admin may also consume that package. The agent should re-check both consumers instead of treating the shared edit as a local implementation detail.&lt;/p&gt;

&lt;p&gt;That is the central idea of an agentic monorepo: an agent can work independently, but only within boundaries that everyone can see and check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common failure modes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The “shared everything” package
&lt;/h3&gt;

&lt;p&gt;One enormous &lt;code&gt;common&lt;/code&gt; package becomes a dumping ground for unrelated code. Prefer packages named after clear, stable responsibilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Invisible dependencies
&lt;/h3&gt;

&lt;p&gt;Imports that climb through several folders and duplicated configuration hide relationships. Use named packages, approved exports and automated import rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running every check for every change
&lt;/h3&gt;

&lt;p&gt;This works at first and becomes painful as the repository grows. Run focused checks for the projects a change could affect, while keeping a complete automated test path for high-risk changes and releases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Treating all apps as one deployment
&lt;/h3&gt;

&lt;p&gt;Repository strategy and deployment strategy are different choices. Each application should have explicit build outputs, environment variables and deployment ownership.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using instruction files as a substitute for architecture
&lt;/h3&gt;

&lt;p&gt;An excellent prompt cannot rescue circular dependencies, ambiguous ownership or a test suite that does not run. Agents amplify the structure already present.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should you use a monorepo?
&lt;/h2&gt;

&lt;p&gt;A monorepo is a strong choice when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;several products are maintained by the same team;&lt;/li&gt;
&lt;li&gt;changes frequently cross application and package boundaries;&lt;/li&gt;
&lt;li&gt;products share types, tooling or stable capabilities;&lt;/li&gt;
&lt;li&gt;reviewing related cross-project changes together is valuable;&lt;/li&gt;
&lt;li&gt;consistent engineering standards matter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Separate repositories may be better when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;products have unrelated teams, technology stacks and release processes;&lt;/li&gt;
&lt;li&gt;access must be isolated at the repository level;&lt;/li&gt;
&lt;li&gt;almost no code or operational knowledge is shared;&lt;/li&gt;
&lt;li&gt;independent ownership matters more than cross-project coordination.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not choose a monorepo simply because large companies use one. Choose it when your projects already share code, people and responsibilities closely enough to benefit from one home.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final takeaway
&lt;/h2&gt;

&lt;p&gt;A monorepo is not primarily about putting files together. It is about making relationships explicit.&lt;/p&gt;

&lt;p&gt;That means a marketing site, admin platform and learning product can remain distinct while sharing the foundations that genuinely belong to the whole organisation.&lt;/p&gt;

&lt;p&gt;Making the repository agentic takes the same idea further. We explain its map, enforce its boundaries, standardise its commands and require proof that changes work. Humans gain a clearer codebase, and agents gain the information they need without being given permission to wander.&lt;/p&gt;

&lt;p&gt;One repository can hold many products. The quality of the architecture depends on whether everyone working inside it, human or agent, can tell where one responsibility ends and another begins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose what to read next
&lt;/h2&gt;

&lt;p&gt;You do not need to read every link. Pick the level that matches where you are now.&lt;/p&gt;

&lt;h3&gt;
  
  
  If the foundations are new
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F" rel="noopener noreferrer"&gt;What is Git?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Client-side_tools/Package_management" rel="noopener noreferrer"&gt;MDN: Package-management basics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  If you want to understand monorepos more deeply
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pnpm.io/workspaces" rel="noopener noreferrer"&gt;pnpm Workspaces&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.dev/docs/kb/what-is-a-monorepo" rel="noopener noreferrer"&gt;Nx: What is a monorepo?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.dev/concepts/decisions/overview" rel="noopener noreferrer"&gt;Nx: Monorepo or polyrepo?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://turborepo.com/docs/core-concepts/package-and-task-graph" rel="noopener noreferrer"&gt;Turborepo: Package and Task Graphs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://turborepo.com/docs/crafting-your-repository/running-tasks" rel="noopener noreferrer"&gt;Turborepo: Running Tasks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  If you want to explore agent-ready repositories
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot" rel="noopener noreferrer"&gt;GitHub: Adding repository custom instructions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/copilot/how-tos/agents/copilot-coding-agent/best-practices-for-using-copilot-to-work-on-tasks" rel="noopener noreferrer"&gt;GitHub: Best practices for coding agents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>beginners</category>
      <category>softwaredevelopment</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
