> For the complete documentation index, see [llms.txt](https://engineering.exile.watch/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://engineering.exile.watch/march-2024/lerna-the-hidden-powerhouse-of-exile.watch/1.-separate-repository-and-monorepo-tool.md).

# 1. Separate repository and monorepo tool

<figure><img src="/files/6T3mkUF582HmwgPcv48x" alt="" width="256"><figcaption><p>exile.watch logo</p></figcaption></figure>

*This page is part of* [Lerna - the hidden powerhouse of exile.watch](/march-2024/lerna-the-hidden-powerhouse-of-exile.watch.md#the-toolkit-i-needed-to-make-it-all-happen) *list - 1/7*

*Following up on our deep dive into exile.watch's use of Lerna, this page tackles the first crucial steps: setting up a separate repository and introducing Lerna as our monorepo tool.*&#x20;

***

## Separate repository

It was fairly straightforward—I created an empty repository through GitHub's UI

## Monorepo tool (Lerna)

Starting with an empty repository, the best approach was to follow the "[starting from scratch](https://lerna.js.org/docs/getting-started#starting-from-scratch)" instructions from the Lerna setup guide, utilizing the `npx lerna init` [CLI](https://en.wikipedia.org/wiki/Command-line_interface) command.

Running `lerna init` got everything prepped for a true *Lerna workspace*.&#x20;

Although I don’t remember the exact output, I initially ended up with the following `lerna.json`:

```json5
// lerna.json
{
  "$schema": "node_modules/lerna/schemas/lerna-schema.json",
  "version": "independent",
  "packages": [
    "packages/*"
  ]
}
```

*As of March 2024*, let’s break down the options and definitions in the above JSON:

### $schema

This refers to [JSON schemas](https://json-schema.org/understanding-json-schema/about), which help to describe your JSON data structure.

### version ("fixed" mode)

{% hint style="info" %}
When using the fixed mode, all the affected packages will be published using the same version. The last published version is recorded in `lerna.json`
{% endhint %}

```
.
├ package.json     # "version": 0.0.0
├ lerna.json       # "version": 1.2.3
└ packages     
  ├ package_A
  │ └ package.json # "version": 1.2.3
  └ package_B      
    └ package.json # "version": 1.2.3
```

### version ("independent" mode)

{% hint style="info" %}
If you decide to use `independent`, then every package has it's own version.&#x20;
{% endhint %}

I went with `independent` option.&#x20;

I opted for this approach because some packages will change more often than others.&#x20;

Also it wasn’t necessary to version the repository's `package.json`, and doing so is [generally not recommended:](https://github.com/lerna/lerna/issues/2879#issuecomment-1471606448)

```
.
├ package.json     # "version": deleted key, "private": true
├ lerna.json       # "version": "independent"
└ packages     
  ├ package_A
  │ └ package.json # "version": 1.2.3
  └ package_B      
    └ package.json # "version": 3.2.1
```

### packages

This is an array of [globs](https://docs.python.org/3/library/glob.html) indicating where packages can be found. By default, it’s set to `["packages/*"]`, which is how configurations for [splinters](https://github.com/exile-watch/splinters/blob/main/lerna.json#L16-L18), [nucleus](https://github.com/exile-watch/nucleus/blob/main/lerna.json#L14-L16) and [writ](https://github.com/exile-watch/writ/blob/main/lerna.json#L14-L16) are structured.

## Updating `package.json` to leverage NPM Workspaces

The last change involved updating `package.json` to make the most of [npm workspaces](https://docs.npmjs.com/cli/v7/using-npm/workspaces):

```jsonp
// package.json
{
  // ...
  {
    "workspaces": [
    "packages/*"
  ],
}
```

***

*With our repository and Lerna setup ready, let's now focus on the second key piece: the module bundler, crucial for efficiently packaging our code.*
