Monorepo Generation
To set up a basic monorepo with default settings, we can just run the command sketch ts monorepo. But we can also create a package preset and use that for the root package of the monorepo.
This is a more customized configuration for the root package:
typescript:
# By default, typescript and oxlint would be added to
# the root package's dependencies
no_default_deps: true
# Pnpm is the default, and if selected, it will generate
# a pnpm-workspace.yaml file
package_manager: pnpm
pnpm_presets:
base:
# All the dirs listed here will be created automatically
# when new monorepos are created
packages:
- packages/*
onlyBuiltDependencies:
- esbuild
minimumReleaseAge: 1440
package_presets:
# Defining a preset for the root package
root:
name: workspace
package_json:
workspaces:
# All dirs listed here are also created automatically
# unless they contain '{', '[', '?' or '!'
- apps/**/test
license: Apache-2.0
devDependencies:
husky: ^9.0.0
# The tsconfig files to generate at the root.
# If left empty, defaults will be used.
ts_config:
- output: tsconfig.options.json
config:
compilerOptions:
verbatimModuleSyntax: true
strict: true
- output: tsconfig.json
config:
files: []
# Literal oxlint configuration to generate at the root
# of the workspace.
# Can be set to `true` to use defaults.
oxlint:
plugins: ["unicorn", "typescript", "oxc"]
Adding Templates
You can also use the with_templates field to automatically generate a certain file structure when the monorepo is generated.
Let's say, for example, that every time that you create a new monorepo, you always want to create a docker directory with a basic dev.dockerfile inside of it, so that you can quickly create a dev environment using docker.
To do that, we add this to the root package's definition:
with_templates:
- templates:
# Relative path from the root of the package
- output: docker/dev.dockerfile
template:
name: dev_dockerfile
content: |
FROM node:23-alpine
COPY . .
EXPOSE {{ docker_dev_port }}
CMD ["npm", "run", "dev"]
vars:
docker_dev_port: 5173
ℹ️ You can also use
--with-template <PRESET_ID|id=TEMPLATE_ID,output=PATH>as a flag to add more templates or templating presets when generating a new package.
Hooks
We can define some commands (which can also be templates) to execute before and/or after generating the new monorepo:
# Commands to run before generation, from the root of the new project
hooks_pre:
- command:
# Inlining a new template definition here,
# but as always, we can use stored templates too
name: pre_hook
content: "echo '{{ greeting }}' > pre.txt"
context:
greeting: hi
# Commands to run after generation, from the root of the new project
hooks_post:
- command:
name: post_hook
content: "echo '{{ greeting }}' > post.txt"
context:
greeting: hi
Example
So after setting everything up, we run the command
sketch ts monorepo --root-package root --pnpm base
And get this tree output:
├── .oxlintrc.json
├── apps
│ └── test
├── docker
│ └── dev.dockerfile
├── package.json
├── packages
├── pnpm-workspace.yaml
├── tsconfig.json
└── tsconfig.options.json
ℹ️ You can use the
-iflag to install dependencies for the root package after creating the new monorepo.