Derived Modular Arch
Start

Quick start

Install the CLI, bootstrap with dma init, run dma check, and wire CI.

Minimal path from an empty or existing project to working DMA enforcement. We assume a TypeScript app with src/ (or you create it via init).

Using an AI agent? Copy the prompt — it suggests skill install, dma init, and verification steps for your repo.

1. Install the CLI

npm install -D @derived-modular/cli

2. Bootstrap the layout

From the app package directory (in a monorepo: apps/web, not the workspace root):

npx @derived-modular/cli init .

init is safe on existing projects — strict skip, never overwrites:

Creates (if missing)Skips
src/, features/, shared/Existing files and folders
app/ — unless pages/ or routes/ already existsdma.config.*, scripts.dma, AGENTS.md markers
dma.config.ts, scripts.dma in package.jsonLint configs
DMA block in AGENTS.md (append-only)services/

Resulting tree (minimal):

src/
├── app/          # or pages/, routes/ — composition root for your framework
├── features/
└── shared/

Do not create services/ upfront — it appears on the first promotion when another module imports the code.

More: dma init · Project layout.

Prefer manual layout? Create the same folders yourself. Optional dma.config.*dma.config.

3. Mount a feature from the composition root

The composition root imports modules only through public/:

// src/app/page.tsx
import { CatalogPage } from "@/features/catalog/public/catalog-page";
import { CheckoutPage } from "@/features/checkout/public/checkout-page";

export default function Page() {
  return (
    <div>
      <CatalogPage />
      <CheckoutPage />
    </div>
  );
}

A feature may pull services/*/public/* and shared/, but not other features. Live example — examples/next-app.

4. Run the check

npx @derived-modular/cli check .

Single app with src/ — one graph. Monorepo root without src/ — the CLI discovers apps (or use --roots). Each root is a separate graph.

Typical first errors:

RuleWhat happenedWhat to do
public-apiImport into features/foo/model, not public/Export the symbol in public/ or import from there
feature-to-featureFeature A imports feature BPromote to services/ or extract to shared/ (second use)
layer-directionImport “upward”, e.g. from shared into featuresReverse the dependency

All rules — dma check. Monorepo — Monorepo guide.

5. Add to CI

npx @derived-modular/cli check . --format json

More — CI.

6. (Optional) Linter in the editor

Fast feedback on save — not a substitute for dma check:

npm install -D @derived-modular/eslint-plugin eslint
// eslint.config.js
import dma from "@derived-modular/eslint-plugin";

export default [
  ...dma.configs.recommended,
  {
    settings: {
      dma: {
        srcRoot: "src",
        compositionRoots: ["app", "pages", "routes"],
      },
    },
  },
];

ESLint can soft-load srcRoot / compositionRoots from dma.config.* when settings.dma is unset. Setup — ESLint.

7. Local growth signals

npx @derived-modular/cli doctor .

doctor does not fail CI (exit 0) but hints when to extract to shared, split segments, or promote a feature to a service. More — dma doctor.

What's next

On this page