<?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>Forem: Ahmed Elsakaan</title>
    <description>The latest articles on Forem by Ahmed Elsakaan (@ixahmedxi).</description>
    <link>https://forem.com/ixahmedxi</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%2F55441%2F849508a6-f630-4809-9549-9c3d6f295ef3.png</url>
      <title>Forem: Ahmed Elsakaan</title>
      <link>https://forem.com/ixahmedxi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ixahmedxi"/>
    <language>en</language>
    <item>
      <title>🎓 Monorepo College Lecture 2: Build Me Up Buttercup</title>
      <dc:creator>Ahmed Elsakaan</dc:creator>
      <pubDate>Sat, 08 Apr 2023 22:59:41 +0000</pubDate>
      <link>https://forem.com/ixahmedxi/monorepo-college-lecture-2-build-me-up-buttercup-410e</link>
      <guid>https://forem.com/ixahmedxi/monorepo-college-lecture-2-build-me-up-buttercup-410e</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/ja/@floraf?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Floraf&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/7e9-RYS8Y6Y?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hello everyone and welcome to the second part of Monorepo College, if you haven't already done so, &lt;a href="https://dev.to/ixahmedxi/monorepo-college-lecture-1-a-beautiful-morning-1jgl"&gt;make sure to read the first part of the series firstly&lt;/a&gt; and come back for this one after.&lt;/p&gt;

&lt;p&gt;In this part, we will be initializing the project, getting all of the initial files out of the way and then configure &lt;a href="https://prettier.io"&gt;Prettier&lt;/a&gt; as well as create the first package of our monorepo which will be a &lt;code&gt;tsconfig&lt;/code&gt; package responsible for sharing &lt;a href="https://typescriptlang.org"&gt;TypeScript&lt;/a&gt; configuration files to the other packages we will create in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting things off the ground
&lt;/h2&gt;

&lt;p&gt;First things first, I always make sure to get the &lt;a href="https://git-scm.com"&gt;git&lt;/a&gt; side of things all setup and ready as the first step into setting up any project, and Acme is no different.&lt;/p&gt;

&lt;p&gt;Let's create a new directory for our project, obviously we will call it &lt;code&gt;Acme&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create an "Acme" directory&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;Acme

&lt;span class="c"&gt;# Change terminal directory to it&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;Acme
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have created the directory for the project and changed directories into it inside our terminal, let's initialise git and create a &lt;code&gt;.gitignore&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Initialize git&lt;/span&gt;
git init

&lt;span class="c"&gt;# If your starting branch is not main, you can change it like so:&lt;/span&gt;
git branch &lt;span class="nt"&gt;-m&lt;/span&gt; main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the &lt;code&gt;.gitignore&lt;/code&gt; file, I usually pick a template from &lt;a href="https://github.com/github/gitignore"&gt;github/gitignore&lt;/a&gt; which is a collection of great &lt;code&gt;.gitignore&lt;/code&gt; file templates. For this project I will be using the &lt;a href="https://github.com/github/gitignore/blob/main/Node.gitignore"&gt;Node&lt;/a&gt; template.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Documentation &amp;amp; community files
&lt;/h3&gt;

&lt;p&gt;In any open source project, you should have a minimum of a &lt;code&gt;README.md&lt;/code&gt;, &lt;code&gt;LICENSE&lt;/code&gt;, &lt;code&gt;CODE_OF_CONDUCT.md&lt;/code&gt;, &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; and &lt;code&gt;SECURITY.md&lt;/code&gt;, these are highly dependent on your project so I won't be providing a template for them however here are some resources that might help you out.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;README.md&lt;/code&gt; - &lt;a href="https://www.makeareadme.com/"&gt;https://www.makeareadme.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LICENSE&lt;/code&gt; - &lt;a href="https://opensource.org/licenses/"&gt;https://opensource.org/licenses/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CODE_OF_CONDUCT.md&lt;/code&gt; - &lt;a href="https://www.contributor-covenant.org/version/2/1/code_of_conduct/"&gt;https://www.contributor-covenant.org/version/2/1/code_of_conduct/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CONTRIBUTING.md&lt;/code&gt; - &lt;a href="https://contributing.md/how-to-build-contributing-md/"&gt;https://contributing.md/how-to-build-contributing-md/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SECURITY.md&lt;/code&gt; - Just explain how to report security vulnerabilities in your project.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Initialising pnpm
&lt;/h3&gt;

&lt;p&gt;For this project, we will be using &lt;a href="https://pnpm.io"&gt;pnpm&lt;/a&gt; as our package manager of choice, but obviously you can use any one you prefer.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;package.json&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Let's firstly create our root level &lt;code&gt;package.json&lt;/code&gt; file for the workspace:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This will create a default &lt;code&gt;package.json&lt;/code&gt; file at the root of our project, the default &lt;code&gt;package.json&lt;/code&gt; is fine but we will change some stuff in ours, here's mine after some changes:&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;"acme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"private"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The next billion dollar startup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Acme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"packageManager"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pnpm@8.1.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"engines"&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;"node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=18.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pnpm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=8.1.1"&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;I will go briefly over some of the stuff I have in the &lt;code&gt;package.json&lt;/code&gt; file but you can always read the documentation on all of them &lt;a href="https://docs.npmjs.com/cli/v9/configuring-npm/package-json"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;packageManager&lt;/code&gt; - This field is read by corepack to automatically pull the package manager with the exact version ensuring that your entire team uses the same package manager and the same version.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;engines&lt;/code&gt; - This is used to specify ranges of Node and package manager versions that our project is compatible with, by default this option will only warn you if you use an incompatible version but we will modify that behaviour to error out. This is again one measure to ensure your whole team are using the same tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;pnpm-workspace.yaml&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;pnpm-workspace.yaml&lt;/code&gt; file is used to tell &lt;code&gt;pnpm&lt;/code&gt; three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This project is a monorepo.&lt;/li&gt;
&lt;li&gt;This is the root of the monorepo.&lt;/li&gt;
&lt;li&gt;Here are the directories that you should expect packages to be located at.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let's create our file, we will have it so that &lt;code&gt;pnpm&lt;/code&gt; knows our packages will be located in &lt;code&gt;apps/&lt;/code&gt;, &lt;code&gt;packages/&lt;/code&gt; or &lt;code&gt;packages/config/&lt;/code&gt;:&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;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;packages/*"&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/config/*"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this in place, we have officially entered monorepo land 🎉&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;.npmrc&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;.npmrc&lt;/code&gt; file is a special file that modifies the default behaviour of your package manager, in our case &lt;code&gt;pnpm&lt;/code&gt;, I'm going to show you the &lt;code&gt;.npmrc&lt;/code&gt; file that we will have and then explain what's going on in there, as always I recommend reading the docs for this as that there are a lot of options that you can specify.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pnpm.io/npmrc"&gt;Read the docs&lt;/a&gt;&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="err"&gt;engine-strict=&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;prefer-workspace-packages=&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;public-hoist-patterns&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="err"&gt;=*prisma*&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;public-hoist-patterns&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="err"&gt;=*eslint*&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;public-hoist-patterns&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="err"&gt;=*prettier*&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;engine-strict=true&lt;/code&gt; will make it so that it will error out if you use an incompatible node version with the project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;prefer-workspace-packages&lt;/code&gt; - this setting tells pnpm to prioritize the installation of packages locally from our monorepo &lt;strong&gt;EVEN&lt;/strong&gt; if that package has a newer version on the npm registry. This setting is useful for the following case scenarios:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;someone merges a new PR with changes to a package, this bumps the version up and publishes it to npm automatically.&lt;/li&gt;
&lt;li&gt;someone else is still working on another change in this package, but now when they commit again the CI operation will pull the npm registry version because that version is newer than the one locally. Suddenly checks in CI are messed up.&lt;/li&gt;
&lt;li&gt;This can obviously be mitigated by pulling from main immediately after the other PR is merged but we will 100% forget to do that sometimes.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;public-hoist-patterns&lt;/code&gt; - By default, pnpm won't hoist any packages other than &lt;code&gt;ESLint&lt;/code&gt; and &lt;code&gt;Prettier&lt;/code&gt; packages to the root &lt;code&gt;node_modules&lt;/code&gt; folder, This is mostly great but because we will be using &lt;a href="https://prisma.io"&gt;Prisma&lt;/a&gt; as our database ORM, it does not play nicely in monorepo settings and hence why we need to add it to our &lt;code&gt;public-hoist-patterns&lt;/code&gt; to make it work. This overrides the default value of &lt;code&gt;Prettier&lt;/code&gt; and &lt;code&gt;ESLint&lt;/code&gt; packages though hence why we need to add them again.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Misc files
&lt;/h3&gt;

&lt;p&gt;Now that we have &lt;code&gt;pnpm&lt;/code&gt; all setup in our workspace, we just need to add a couple more files before we get to the fun stuff.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;.editorconfig&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://editorconfig.org"&gt;EditorConfig&lt;/a&gt; is a tool that defines coding styles for multiple editors and IDEs, this will be somewhat of a fallback for users who don't have prettier formatting in their editor and prettier does support &lt;code&gt;.editorconfig&lt;/code&gt; by default so there is no reason to not have it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
indent_style &lt;span class="o"&gt;=&lt;/span&gt; space
indent_size &lt;span class="o"&gt;=&lt;/span&gt; 2
end_of_line &lt;span class="o"&gt;=&lt;/span&gt; lf
charset &lt;span class="o"&gt;=&lt;/span&gt; utf-8
trim_trailing_whitespace &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false
&lt;/span&gt;insert_final_newline &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;.nvmrc&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/nvm-sh/nvm"&gt;NVM&lt;/a&gt; is a Node version manager commonly used to install multiple versions of Nodejs on one system, by having a &lt;code&gt;.nvmrc&lt;/code&gt; file we tell nvm which nodejs version to use with this project.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting up TypeScript
&lt;/h3&gt;

&lt;p&gt;In our workspace, we will be using one TypeScript version for the entire monorepo, this means that we will need to install it in our root &lt;code&gt;package.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; typescript @types/node &lt;span class="nt"&gt;-w&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-w&lt;/code&gt; flag is needed to install dependencies to the root &lt;code&gt;package.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;We will be setting up the &lt;code&gt;@acme/tsconfig&lt;/code&gt; package later on after prettier to share &lt;code&gt;tsconfig&lt;/code&gt; presets to our future packages.&lt;/p&gt;

&lt;p&gt;If you are using VSCode, your editor is probably using TypeScript v4.9 or something along those lines which doesn't align with our version and will cause errors in particularly using multiple extends. To fix this we need to create a new file at &lt;code&gt;.vscode/settings.json&lt;/code&gt; and include this code which will tell VSCode to use our workspace version of TypeScript:&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;"typescript.tsdk"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node_modules/typescript/lib"&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;h3&gt;
  
  
  Setting up Prettier
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://prettier.io"&gt;Prettier&lt;/a&gt; is a code formatter, it supports many languages and editors so we will be using it to ensure a consistent coding style throughout our project and provide format on save capabilities. We will also be using some prettier plugins to give us more functionality.&lt;/p&gt;

&lt;h4&gt;
  
  
  Install prettier and plugins
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; prettier @types/prettier @ianvs/prettier-plugin-sort-imports prettier-plugin-packagejson prettier-plugin-jsdoc prettier-plugin-tailwindcss &lt;span class="nt"&gt;-w&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Configuring prettier
&lt;/h4&gt;

&lt;p&gt;To configure prettier, let's create a &lt;code&gt;prettier.config.cjs&lt;/code&gt; file that will host our configuration options.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @typedef {import('@ianvs/prettier-plugin-sort-imports').PluginConfig} SortImportsConfig */&lt;/span&gt;
&lt;span class="cm"&gt;/** @typedef {import('prettier').Config} PrettierConfig */&lt;/span&gt;

&lt;span class="cm"&gt;/** @type {PrettierConfig | SortImportsConfig} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;semi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;singleQuote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;trailingComma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ianvs/prettier-plugin-sort-imports&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prettier-plugin-packagejson&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prettier-plugin-jsdoc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prettier-plugin-tailwindcss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;pluginSearchDirs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;importOrder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;TYPES&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;TYPES&amp;gt;^[./]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;THIRD_PARTY_MODULES&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^@acme/(.*)$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^@/(.*)$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^[./]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;importOrderSeparation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;importOrderSortSpecifiers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;importOrderMergeDuplicateImports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&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 3 options are self explanatory, then we list the plugins and the important bit here after is the &lt;code&gt;pluginSearchDirs: false&lt;/code&gt; which without it, &lt;code&gt;prettier-plugin-tailwindcss&lt;/code&gt; acts weirdly and won't work as expected.&lt;/p&gt;

&lt;p&gt;Next up we configure the import statements order that we want to use, whenever we use &lt;code&gt;""&lt;/code&gt; it's to add separations between our import statements and we set the default separation behaviour to false instead.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;importOrderSortSpecifiers&lt;/code&gt; option will format different specifiers in an import statement such as &lt;code&gt;type&lt;/code&gt; imports and normal imports.&lt;/p&gt;

&lt;p&gt;Lastly, the &lt;code&gt;importOrderMergeDuplicateImports&lt;/code&gt; will merge import statements from the same source into one import statement.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;.prettierignore&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;.prettierignore&lt;/code&gt; file is used to exclude prettier from formatting certain files, we will use this to tell prettier to not format any &lt;code&gt;dist&lt;/code&gt; and &lt;code&gt;.next&lt;/code&gt; folders as well as the &lt;code&gt;pnpm-lock.yaml&lt;/code&gt; file.&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="s"&gt;.next&lt;/span&gt;
&lt;span class="s"&gt;pnpm-lock.yaml&lt;/span&gt;
&lt;span class="s"&gt;dist&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Adding format scripts to our package.json
&lt;/h4&gt;

&lt;p&gt;In our root &lt;code&gt;package.json&lt;/code&gt; file, let's add some scripts that we can run to format the entire workspace with prettier. Add this to our already existing &lt;code&gt;package.json&lt;/code&gt; file:&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="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;"format:check"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier --check ."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"format:write"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier --write ."&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 now run &lt;code&gt;pnpm format:write&lt;/code&gt; to format all of the files in our project!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating our first package
&lt;/h2&gt;

&lt;p&gt;Now that we have pnpm and prettier all setup, we are ready to introduce the first package to our monorepo, exciting times!&lt;/p&gt;

&lt;p&gt;Since we have already installed &lt;code&gt;typescript&lt;/code&gt; in our monorepo, the next step is to setup TypeScript in our workspace in a way that will make it easy to use it in our future packages.&lt;/p&gt;

&lt;p&gt;We will be creating a &lt;code&gt;tsconfig&lt;/code&gt; package that shares TS configuration presets to our packages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initializing the package
&lt;/h3&gt;

&lt;p&gt;Let's create the directory that will host our package at &lt;code&gt;packages/config&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;packages
&lt;span class="nb"&gt;mkdir &lt;/span&gt;packages/config
&lt;span class="nb"&gt;mkdir &lt;/span&gt;packages/config/tsconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First things first, let's create a &lt;code&gt;package.json&lt;/code&gt; file for our package:&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;"@acme/tsconfig"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"private"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Presets for common tsconfig.json configurations"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Acme"&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;Don't forget to include &lt;code&gt;"private": true,&lt;/code&gt; since we won't be publishing it to NPM.&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating our tsconfigs
&lt;/h4&gt;

&lt;p&gt;Now that we have the &lt;code&gt;package.json&lt;/code&gt; for our &lt;code&gt;@acme/tsconfig&lt;/code&gt; package setup, we then need to install some dependencies for it.&lt;/p&gt;

&lt;p&gt;I personally am a big advocate for writing the least amount of &lt;code&gt;tsconfig&lt;/code&gt; possible, and the &lt;a href="https://github.com/tsconfig/bases"&gt;tsconfig/bases&lt;/a&gt; package serves as a great source for getting &lt;code&gt;tsconfig&lt;/code&gt; templates.&lt;/p&gt;

&lt;p&gt;Let's install some of them:&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; tsconfig add &lt;span class="nt"&gt;-D&lt;/span&gt; @tsconfig/node18 @tsconfig/strictest @tsconfig/next @tsconfig/vite-react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;code&gt;--filter&lt;/code&gt; option, these dependencies will be installed in &lt;code&gt;packages/config/tsconfig/package.json&lt;/code&gt; file and &lt;strong&gt;NOT&lt;/strong&gt; the root &lt;code&gt;package.json&lt;/code&gt; file.&lt;/p&gt;

&lt;h5&gt;
  
  
  Base tsconfig
&lt;/h5&gt;

&lt;p&gt;Now that we have our dependencies installed, let's create our first preset which will be named &lt;code&gt;base.json&lt;/code&gt; in &lt;code&gt;packages/config/tsconfig&lt;/code&gt;, this file will be a base configuration that all the other ones will extend from:&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://json.schemastore.org/tsconfig"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"display"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Base"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&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;"@tsconfig/strictest/tsconfig"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@tsconfig/node18/tsconfig"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&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;"allowJs"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"checkJs"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"moduleResolution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bundler"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"esnext"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"resolvePackageJsonExports"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"verbatimModuleSyntax"&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="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;Since we are using TypeScript version 5, we can extend multiple tsconfigs rather than only one. In our base configuration we extend the &lt;code&gt;strictest&lt;/code&gt; and the &lt;code&gt;node18&lt;/code&gt; presets and then we modify them slightly to better fit our needs.&lt;/p&gt;

&lt;p&gt;Some of the worthy modifications include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;moduleResolution&lt;/code&gt; we set the base module resolution to TypeScript 5's new &lt;code&gt;bundler&lt;/code&gt;, since we will be using tsup throughout this monorepo for bundling, this serves as a great resolution and allows us to enable &lt;code&gt;resolvePackageJsonExports&lt;/code&gt; which will enable easy multi exports support for out packages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;resolvePackageJsonExports&lt;/code&gt; is a field that forces TypeScript to read and resolve files from a package's &lt;code&gt;exports&lt;/code&gt; field in it's &lt;code&gt;package.json&lt;/code&gt; file, this allows us to easily create multiple exports for our packages and avoids us using hacks such as &lt;code&gt;typesVersions&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  React tsconfig
&lt;/h5&gt;

&lt;p&gt;The next tsconfig file on our list is a react specific one, this will serve as a tsconfig file for all of our react packages such as the UI components library package coming in the future, create a &lt;code&gt;react.json&lt;/code&gt; file in our package with the following content:&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://json.schemastore.org/tsconfig"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"display"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Base"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&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;"./base.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@tsconfig/vite-react/tsconfig"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&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;"moduleResolution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bundler"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowJs"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we simply extend the base configuration and &lt;code&gt;@tsconfig/vite-react/tsconfig&lt;/code&gt;, enable the &lt;code&gt;bundler&lt;/code&gt; moduleResolution since the &lt;code&gt;vite-react&lt;/code&gt; preset overrides the one in our &lt;code&gt;base.json&lt;/code&gt; and lastly allow javascript files so that we can also type check them.&lt;/p&gt;

&lt;h5&gt;
  
  
  Next.js tsconfig
&lt;/h5&gt;

&lt;p&gt;The last file that we will create for our package will be a Next.js specific &lt;code&gt;tsconfig&lt;/code&gt; preset called &lt;code&gt;nextjs.json&lt;/code&gt;:&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://json.schemastore.org/tsconfig"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"display"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nextjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&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;"./base.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@tsconfig/next/tsconfig"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&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;"moduleResolution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nodenext"&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 extend the &lt;code&gt;base.json&lt;/code&gt; preset again and also this time &lt;code&gt;@tsconfig/next/tsconfig&lt;/code&gt;. We also modify the &lt;code&gt;moduleResolution&lt;/code&gt; to &lt;code&gt;nodenext&lt;/code&gt; because Next.js does not work with the &lt;code&gt;bundler&lt;/code&gt; moduleResolution and will replace it with &lt;code&gt;node&lt;/code&gt; upon running the &lt;code&gt;dev&lt;/code&gt; command which we do not want.&lt;/p&gt;

&lt;h4&gt;
  
  
  Plugging everything up
&lt;/h4&gt;

&lt;p&gt;Now that we have &lt;code&gt;base.json&lt;/code&gt;, &lt;code&gt;react.json&lt;/code&gt; and &lt;code&gt;nextjs.json&lt;/code&gt; in our package, we are almost there to have a fully functional package that we can use throughout our monorepo. The last part is to specify in our &lt;code&gt;package.json&lt;/code&gt; file that we expect these files to be accessible. This is done through the &lt;code&gt;files&lt;/code&gt; property. And so after all of this work our final &lt;code&gt;package.json&lt;/code&gt; of &lt;code&gt;@acme/tsconfig&lt;/code&gt; should look like this:&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;"@acme/tsconfig"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"private"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Presets for common tsconfig.json configurations"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Acme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"files"&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;"./base.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./nextjs.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./react.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;"devDependencies"&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;"@tsconfig/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;"^1.0.5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@tsconfig/node18"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@tsconfig/strictest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@tsconfig/vite-react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.0.1"&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 now have a fully functional monorepo package and to start using it, let's create a &lt;code&gt;tsconfig.json&lt;/code&gt; file at the root of our monorepo that will handle providing a TypeScript configuration for the entire monorepo (unless another &lt;code&gt;tsconfig.json&lt;/code&gt; file is in a package, that will be used instead for the package). We do this to mainly provide ESLint with a &lt;code&gt;tsconfig.json&lt;/code&gt; file for our root files such as the &lt;code&gt;prettier.config.cjs&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;We firstly need to install &lt;code&gt;@acme/tsconfig&lt;/code&gt; in our monorepo's root package.json, to do this we simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; @acme/tsconfig &lt;span class="nt"&gt;-w&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now create a &lt;code&gt;tsconfig.json&lt;/code&gt; file at the root of our repository with the following content:&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;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@acme/tsconfig/base"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&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;"noEmit"&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="nl"&gt;"include"&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="s2"&gt;".eslintrc.cjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"**/*.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"**/*.tsx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"**/*.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"**/*.jsx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"**/*.cjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"**/*.mjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"**/*.cts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"**/*.mts"&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 can see how we are now extending from &lt;code&gt;@acme/tsconfig/base&lt;/code&gt; this points to &lt;code&gt;packages/config/tsconfig/base.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To test that this is working, we can define a new property in our &lt;code&gt;prettier.config.cjs&lt;/code&gt; file that does not exist on the prettier options type and we can expect typescript to display an error. This happens as that we allow JavaScript files in our &lt;code&gt;base&lt;/code&gt; tsconfig and we also set the &lt;code&gt;checkJs&lt;/code&gt; property to true, so we don't need to explicitly define &lt;code&gt;// @ts-check&lt;/code&gt; for every JS file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;And with all of that, we now have a fully setup &lt;code&gt;prettier&lt;/code&gt; configuration as well as we created our first package, &lt;code&gt;@acme/tsconfig&lt;/code&gt;. We also setup TypeScript configuration presets that we will be able to use once we start adding a Next.js application, a React UI components library...etc&lt;/p&gt;

&lt;p&gt;We will use the latest and greatest features of TypeScript v5 in this monorepo to give us the best DX possible and let us move quicker creating and developing apps and packages.&lt;/p&gt;

&lt;p&gt;I know this might have been a very dense post, this is why I don't expect everyone to completely understand everything that we have gone through here. For that, feel free to &lt;a href="https://twitter.com/ixahmedxii"&gt;DM me on Twitter&lt;/a&gt; with all of your questions and I will help you out.&lt;/p&gt;

&lt;h2&gt;
  
  
  One last thing
&lt;/h2&gt;

&lt;p&gt;As the previous part, this post title is completely unrelated to the topic. This part's title is inspired by The Foundations' record, "Build Me Up Buttercup" release in 1968. Give it a listen!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/hSofzQURQDk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>monorepo</category>
      <category>typescript</category>
      <category>prettier</category>
      <category>pnpm</category>
    </item>
    <item>
      <title>🎓 Monorepo college lecture 1: a beautiful morning</title>
      <dc:creator>Ahmed Elsakaan</dc:creator>
      <pubDate>Fri, 07 Apr 2023 07:06:21 +0000</pubDate>
      <link>https://forem.com/ixahmedxi/monorepo-college-lecture-1-a-beautiful-morning-1jgl</link>
      <guid>https://forem.com/ixahmedxi/monorepo-college-lecture-1-a-beautiful-morning-1jgl</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/de/@jfelise?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Josh Felise&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/morning?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Embark on a thrilling journey to Monorepo Land, where code sharing and team collaboration are the order of the day! 🚄🌅&lt;/p&gt;

&lt;p&gt;Greetings, fellow monorepo enthusiasts! You might recall &lt;a href="https://twitter.com/ixahmedxii/status/1640859386678591489?s=46&amp;amp;t=NbnVtEhh4GCsCcmQ2Y0HlA"&gt;that tweet&lt;/a&gt; from a while ago, but the wait is over. Monorepo College has arrived, and it's time to dive in!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Monorepo Mission
&lt;/h2&gt;

&lt;p&gt;Monorepo configurations can be challenging to set up, but once you nail them down, they should fade into the background, allowing you to focus on what truly matters. We've all been there: a monorepo is running smoothly, only for a tiny change to wreak havoc and send us back to configuration purgatory.&lt;/p&gt;

&lt;p&gt;In reality, monorepos should streamline your workflow through shared code, so you can concentrate on delivering quality products rather than wrestling with broken configs.&lt;/p&gt;

&lt;p&gt;It's no secret that monorepo conventions are hard to find, and everyone seems to draw inspiration from different sources. So, how can we be confident that our current setup will scale effectively down the road?&lt;/p&gt;

&lt;p&gt;Introducing Monorepo College, a series of blog posts and YouTube videos designed to guide you through building a monorepo starter kit from scratch. The primary goal is to teach you how to architect a monorepo setup, but if you prefer to skip the process, the starter kit will be available on GitHub after the series.&lt;/p&gt;

&lt;p&gt;In this first installment, we'll introduce the world of monorepos, outline the series' scope, and discuss some conventions to consider during setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monorepos: The What and the Why
&lt;/h2&gt;

&lt;p&gt;A monorepo, short for "monolithic repository," is a single repository housing multiple projects, packages, or codebases. This setup enables you to store all your projects in one location, facilitating code sharing between them.&lt;/p&gt;

&lt;p&gt;To learn more about the concept of monorepos, check out &lt;a href="https://monorepo.tools/"&gt;Monorepo tools&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Monorepo Marvel: Advantages
&lt;/h2&gt;

&lt;p&gt;Monorepos boast several benefits over traditional polyrepos (multiple repositories) setups, including:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Effortless code sharing:&lt;/strong&gt; With a monorepo, you can easily share components, such as a UI component, across multiple applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent tooling:&lt;/strong&gt; Monorepos enable you to standardize tool configurations across packages, resulting in a unified toolset. For example, an ESLint config package can be used by all packages in the monorepo, ensuring consistent lint rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified dependency management:&lt;/strong&gt; Monorepos offer a clearer view of package dependencies, and with tools like pnpm, you can update dependencies across packages with a single command. This helps avoid different projects using different versions of the same dependency, such as React.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While this list is by no means exhaustive, it highlights how monorepos can enhance the development process for more complex codebases.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Monorepo Matrix: When It Works and When It Doesn't
&lt;/h2&gt;

&lt;p&gt;Monorepos can be a perfect fit for some projects, but not for others. Generally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your code is highly complex and needs to be broken down into smaller, independently managed components, a monorepo is the way to go. For a simple portfolio website, a monorepo is overkill.&lt;/li&gt;
&lt;li&gt;If your team works on distinct areas of the product, a monorepo is a must.&lt;/li&gt;
&lt;li&gt;(Possibly a hot take) If you're building a startup or a project with an existing or planned team, a monorepo is likely your best bet.&lt;/li&gt;
&lt;li&gt;If you're developing an open-source library with multiple parts, a monorepo is essential. For a simple utility library, there's no need for one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, the more complex the codebase, the more a monorepo makes sense.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Our Monorepo Masterpiece
&lt;/h2&gt;

&lt;p&gt;Before diving into the objectives of this series, let's introduce Acme, our imaginary startup. Throughout this series, we'll create a monorepo for Acme, starting from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Envisioning the Monorepo Structure
&lt;/h2&gt;

&lt;p&gt;Here's a potential layout for our monorepo, which may change as we progress:&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="err"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;apps&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;docs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;└──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;└──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;packages&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;api&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;config&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;eslint&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;playwright&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;storybook&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tailwind&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tsconfig&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tsup&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;│&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;└──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;vitest&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;database&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;features&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;storybook&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;└──&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ui&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Apps
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;apps&lt;/code&gt; folder will house all of Acme's applications, such as mobile and web apps, marketing sites, and product-specific applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  packages/config
&lt;/h3&gt;

&lt;p&gt;Before discussing the &lt;code&gt;packages&lt;/code&gt; folder, let's examine the &lt;code&gt;packages/config&lt;/code&gt; directory. This folder will contain configurations for tools used by other packages in the monorepo, such as shared tsconfig presets, tailwind, tsup, vitest, and more.&lt;/p&gt;

&lt;p&gt;Centralizing tool configurations helps streamline maintenance and troubleshooting.&lt;/p&gt;

&lt;h3&gt;
  
  
  packages
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;packages&lt;/code&gt; directory will host various packages used by the &lt;code&gt;apps&lt;/code&gt;. For example, a &lt;code&gt;ui&lt;/code&gt; package will contain shared UI components used by the applications.&lt;/p&gt;

&lt;p&gt;We'll also create a &lt;code&gt;packages/api&lt;/code&gt; for our tRPC API, which will communicate with and fetch data from our database stored in &lt;code&gt;packages/database&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rationale Behind the Decisions
&lt;/h3&gt;

&lt;p&gt;Our layout prioritizes flexibility and modularity. Everything is separated in little packages throughout the monorepo and they all come together to form a fully functional application.&lt;/p&gt;

&lt;p&gt;If we wanted to replace tsup, for example, we'd only need to modify &lt;code&gt;packages/config/tsup&lt;/code&gt;. You could opt for a more modular name like &lt;code&gt;packages/config/bundler&lt;/code&gt;, but we're confident tsup will serve us well for now.&lt;/p&gt;

&lt;p&gt;Most packages (excluding config) won't be used by many apps, and usage should not determine whether code is split into a package. In essence, if a product area can be isolated in its own package, it probably should. Isolating UI components and the API allows us to replace applications while retaining easy access to these components. This approach is also ideal for teamwork, as individuals can focus solely on their assigned packages, improving their development experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools and Technologies to Tackle
&lt;/h2&gt;

&lt;p&gt;Throughout this series, we'll explore various technologies and learn how to configure them in a monorepo context, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pnpm&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Storybook&lt;/li&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;Clerk&lt;/li&gt;
&lt;li&gt;Prisma&lt;/li&gt;
&lt;li&gt;Tsup&lt;/li&gt;
&lt;li&gt;ESLint&lt;/li&gt;
&lt;li&gt;Prettier&lt;/li&gt;
&lt;li&gt;Changesets&lt;/li&gt;
&lt;li&gt;Tailwindcss&lt;/li&gt;
&lt;li&gt;Vitest&lt;/li&gt;
&lt;li&gt;Playwright&lt;/li&gt;
&lt;li&gt;NX&lt;/li&gt;
&lt;li&gt;Turborepo&lt;/li&gt;
&lt;li&gt;Github actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The primary focus will be on general configuration principles to help you better understand and apply these techniques to any technology in your monorepo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Homework
&lt;/h2&gt;

&lt;p&gt;Each installment will include optional homework or challenges to deepen your understanding of monorepos.&lt;/p&gt;

&lt;p&gt;For this part, try this simple task:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a monorepo with &lt;code&gt;packages/is-odd&lt;/code&gt; and &lt;code&gt;packages/is-even&lt;/code&gt;. The &lt;code&gt;packages/is-even&lt;/code&gt; &lt;strong&gt;should return the inverse of&lt;/strong&gt; &lt;code&gt;packages/is-odd&lt;/code&gt;. This exercise will familiarize you with sharing code between packages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to send me your creation via &lt;a href="https://twitter.com/ixahmedxii"&gt;Twitter DM&lt;/a&gt;, and I'll provide feedback!&lt;/p&gt;

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

&lt;p&gt;Getting monorepos right can be challenging, but when set up correctly, they should streamline your development process. Monorepo College aims to provide insights into monorepo structures and configurations, helping you create efficient and effective monorepos that boost, rather than hinder, your development.&lt;/p&gt;

&lt;p&gt;Join me in the next installment, where we'll begin building Acme. Long live Acme!&lt;/p&gt;

&lt;h2&gt;
  
  
  One last thing
&lt;/h2&gt;

&lt;p&gt;Each post will feature an unrelated title inspired by a song. This episode's title comes from The Rascals' "A Beautiful Morning," released in 1968. Give it a listen!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ykLVZR7RG_w"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>monorepo</category>
      <category>webdev</category>
      <category>typescript</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
