Skip to content
DMNO
✨ If you've tried DMNO or looked through the docs, let us know what you think!

Monorepo guide

While DMNO works great in a traditional single-purpose repo, it was designed from the ground up to handle the challenges of working in a monorepo.

Monorepo structure

Rather than having only a single .dmno folder at the root of your project, in a monorepo each child project/service will have its own .dmno folder too.

  • Directory/ (root of your project)
    • Directory.dmno (your root service config)
      • config.mts
    • Directorypackages
      • Directorymy-package
        • Directory.dmno
          • config.mts (config for my-package service)
      • Directoryanother-package
        • Directory.dmno
          • config.mts (config for another-package service)
    • package.json

If you’re starting fresh with DMNO, then the dmno init command will detect all your services and help initialize DMNO in each.

Detecting child services

By default, DMNO will rely on your existing tooling to detect where potential child projects are found. This is usually an array of paths or glob patterns.

We look in the following locations:

Workspace toolGlobs location
npm, yarn, bunpackage.json
workspaces
pnpmpnpm-workspace.yaml
packages
moonrepo.moon/workspace.yml
projects

In some situations, like a polyglot repo, or a large repo that has multiple smaller monorepos within it, you may need an alternate way of defining where to look for DMNO services. In this case, you can create a workspace.yaml in your workspace root’s .dmno folder. If this file is found, it will override everything else.

.dmno/workpace.yaml
projects:
- "packages/*" # glob pattern
- "libs/some-lib" # exact path

Running concurrent DMNO tasks

When running tasks within a monorepo, you often want to orchestrate many tasks on many child projects at once, using something like Turborepo. Since many of those tasks may rely on DMNO to load and resolve config, this could slow things down due to unnecessary repeated work.

To solve this, dmno run boots up a server that other DMNO instances within child processes are able to communicate with, meaning we can load and resolve your config just once. To take advantage of this optimization, run your command via dmno run and you should be good to go - for example dmno run -- turbo build.

Sharing config across services

As outlined in our schema guide, services in monorepos are allowed to pick items from other services. While there are other mechanisms for reusing values from other services, pick allows you to reuse the entire item - including all other properties (e.g., description, validation logic).

If you find your services have duplicate config items, or an item could be derived from one in another service, consider using pick() to keep things DRY.