www/src/content/docs/docs/set-up-a-monorepo.mdx
While, drop-in mode is great for simple projects, we recommend using a monorepo for projects that are going to have multiple packages.
:::tip We created a monorepo template for your SST projects. :::
However, setting up a monorepo with everything you need can be surprisingly tricky. To fix this we created a template for a TypeScript monorepo that uses npm workspaces.
To use this template.
Head over to github.com/sst/monorepo-template
Click on Use this template and create a new repo.
Clone the repo.
From the project root, run the following to rename it to your app.
npx replace-in-file "/monorepo-template/g" "MY_APP" "./**/*" --verbose
Install the dependencies.
npm install
Now just run npx sst dev from the project root.
The app is split into the separate packages/ and an infra/ directory.
my-sst-app
├─ sst.config.ts
├─ package.json
├─ packages
│ ├─ functions
│ ├─ scripts
│ └─ core
└─ infra
The packages/ directory has your workspaces and this is in the root package.json.
"workspaces": [
"packages/*"
]
Let's look at it in detail.
The packages/ directory includes the following:
core/
This directory includes shared code that can be used by other packages. These are
defined as modules. For example, we have an Example module.
export namespace Example {
export function hello() {
return "Hello, world!";
}
}
We export this using the following in the package.json:
"exports": {
"./*": [
"./src/*\/index.ts",
"./src/*.ts"
]
}
This will allow us to import the Example module by doing:
import { Example } from "@monorepo-template/core/example";
Example.hello();
We recommend creating new modules for the various domains in your project. This roughly follows Domain Driven Design.
We also have Vitest configured for testing this package with the sst shell CLI.
npm test
functions/
This directory includes our Lambda functions. It imports from the core/
package by using it as a local dependency.
scripts/
This directory includes scripts that you can run on your SST app using the sst shell CLI
and tsx. For example, to the run the example
scripts/src/example.ts, run the following from packages/scripts/.
npm run shell src/example.ts
You can add additional packages to the packages/ directory. For example, you might add a frontend/ and a backend/ package.
The infra/ directory allows you to logically split the infrastructure of your app into separate files. This can be helpful as your app grows.
In the template, we have an api.ts, and storage.ts. These export resources that can be used in the other infrastructure files.
export const bucket = new sst.aws.Bucket("MyBucket");
We then dynamically import them in the sst.config.ts.
async run() {
const storage = await import("./infra/storage");
await import("./infra/api");
return {
MyBucket: storage.bucket.name
};
}
Finally, some of the outputs of our components are set as outputs for our app.