Rule Writing

CLAUDE.md for Nx Monorepos

Nx provides generators, executors, and project graph analysis. AI generates manual setup that misses affected commands, caching, and code generation.

7 min read·March 20, 2025

Nx knows which projects changed — AI rebuilds everything regardless

Generators, affected commands, project graph, module boundaries, and Nx Cloud caching

Why Nx Monorepos Need Generator and Graph Rules

Nx is a monorepo build system with batteries included: code generators (scaffolding), project graph analysis (understands dependencies), affected commands (test/build only what changed), computation caching (skip work already done), and module boundary enforcement (prevent circular imports). AI ignores all of these, creating files manually, running all tests regardless of changes, and importing across boundaries without restrictions.

Nx differs from Turborepo in two key ways: Nx provides code generators (nx generate) for scaffolding libraries, apps, and components with consistent structure. And Nx analyzes the project graph at the code level (import analysis), not just at the package.json level. This means Nx knows which library is affected by a code change, even without explicit workspace dependencies.

These rules target Nx 19+ with the integrated monorepo style (recommended). They cover generators, affected commands, caching, module boundaries, and Nx Cloud.

Rule 1: Nx Generators for All Scaffolding

The rule: 'Use Nx generators for all scaffolding: nx generate @nx/react:library shared-ui, nx generate @nx/node:application api-server, nx generate @nx/react:component Button --project=shared-ui. Generators create files with correct project structure, configuration, and test setup. Never create library or application directories manually — the generator handles: project.json, tsconfig, jest/vitest config, and workspace references.'

For custom generators: 'Create project-specific generators for repeated patterns: nx generate @nx/plugin:generator my-feature. Custom generators scaffold features with your project conventions: API routes, service classes, test files, and documentation. Use for: new feature modules, new API endpoints, new database models — anything you create more than twice.'

AI creates files manually: mkdir libs/shared-ui && touch libs/shared-ui/index.ts. This skips: project.json registration, TypeScript paths configuration, test setup, and lint configuration. The generator does all of this in one command — and the project graph immediately recognizes the new library.

  • nx generate for all scaffolding: libraries, apps, components, features
  • Generators create: project.json, tsconfig, test config, workspace refs
  • Custom generators for project-specific patterns — create once, use everywhere
  • Never create libraries/apps manually — the graph needs project.json
  • @nx/react, @nx/node, @nx/angular, @nx/nest — framework-specific generators
💡 Generators = Consistency

nx generate creates libraries with correct project.json, tsconfig, test config, and workspace references — in one command. AI creates files manually and misses half the configuration. Generators enforce structure that the project graph depends on.

Rule 2: Affected Commands — Only What Changed

The rule: 'Use nx affected for all CI tasks: nx affected -t build test lint. This runs tasks only on projects affected by the current changes (compared to the base branch). Nx analyzes the project graph to determine: which files changed, which projects those files belong to, and which projects depend on those projects. Unaffected projects are skipped entirely.'

For CI: 'Set the base branch: NX_BASE=main (or origin/main for CI). Nx compares HEAD against the base to determine changes. In GitHub Actions: nx affected -t build test lint --base=origin/main. For PRs: only the PR changes are analyzed. For main branch: compare against the last successful CI run (use nx-set-shas action).'

AI runs nx run-many -t build test lint (runs everything) or individual nx build commands per project. affected is the most impactful CI optimization — a change in one library runs tests for that library and its dependents, not the entire monorepo.

affected = Smart CI

nx affected -t test runs tests only on projects affected by your changes. A change in libs/shared-ui tests shared-ui + apps that import it — not the entire monorepo. The most impactful CI optimization for any Nx project.

Rule 3: Project Graph and Module Boundaries

The rule: 'Use the @nx/enforce-module-boundaries ESLint rule to prevent invalid imports: libraries cannot import from applications, UI libraries cannot import from data libraries, and feature libraries cannot depend on other feature libraries directly. Define boundaries with tags: { "scope": "shared" }, { "type": "feature" }, { "type": "ui" }, { "type": "data" }. Configure constraints in .eslintrc.json.'

For the project graph: 'View with nx graph — a visual representation of all projects and their dependencies. Use it to: understand the impact of changes, identify circular dependencies, and verify module boundary compliance. The graph is computed from actual import analysis — not package.json declarations.'

For library types: 'Organize libraries by type: feature (smart components + state), ui (presentational components), data (API clients + state management), util (pure utility functions). Dependencies flow: feature → ui + data + util, data → util, ui → util. Never feature → feature or ui → data — enforce with module boundaries.'

  • @nx/enforce-module-boundaries lint rule — prevent invalid imports
  • Tags: scope (shared, app-specific), type (feature, ui, data, util)
  • nx graph for visual dependency map — import analysis, not just package.json
  • Feature → ui + data + util — never feature → feature or ui → data
  • Circular dependencies caught by the graph — fix before they become entangled
⚠️ Boundaries Prevent Spaghetti

@nx/enforce-module-boundaries prevents: feature importing from feature, UI importing from data, app code in libraries. Without it, a 50-library monorepo becomes a tangled dependency graph that nobody can refactor.

Rule 4: Task Caching and Nx Cloud

The rule: 'Nx caches task outputs locally by default — .nx/cache. Define cacheable operations in nx.json: { "targetDefaults": { "build": { "cache": true, "inputs": ["default", "^default"], "outputs": ["{projectRoot}/dist"] } } }. inputs defines what invalidates the cache (source files, dependencies). outputs defines what to store (build artifacts). If inputs have not changed, the task is skipped and outputs are restored from cache.'

For Nx Cloud: 'Enable remote caching with Nx Cloud: npx nx connect. Team members and CI share the cache — if anyone has built a project with the same inputs, the output is already cached. Nx Cloud also provides: distributed task execution (split CI across agents), GitHub PR status checks, and historical analytics.'

For inputs: 'Define what affects each task: { "inputs": ["default", "^default", { "env": "NODE_ENV" }] }. default = project source files. ^default = dependency source files. env = environment variables. Named inputs for reuse: { "namedInputs": { "production": ["default", "!{projectRoot}/**/*.spec.ts"] } }.'

Rule 5: Nx-Specific Patterns

The rule: 'Use project.json for per-project configuration (preferred in integrated repos) or package.json scripts (for package-based repos). Use nx.json for workspace-wide configuration: target defaults, named inputs, cache settings, and default generator options. Use libs/ for libraries, apps/ for applications — Nx convention, not enforced but strongly recommended.'

For testing: 'Use nx test project-name for individual project tests. Use nx affected -t test for affected tests only. Use nx run-many -t test --parallel=5 for parallel test execution. Configure test runners per project type: Jest for React, Vitest for Vite projects, Playwright for E2E. Nx orchestrates the test runner — it does not replace it.'

For migration: 'Use nx migrate for updating Nx and running code migrations: nx migrate latest && nx migrate --run-migrations. Nx provides code migrations that automatically update your configuration, dependencies, and even source code for breaking changes. Run after every major Nx update.'

Complete Nx Rules Template

Consolidated rules for Nx monorepo projects.

  • nx generate for all scaffolding — never create libraries/apps manually
  • nx affected for CI — only build/test/lint what changed — NX_BASE for comparison
  • @nx/enforce-module-boundaries — tags for scope and type — prevent invalid imports
  • nx graph for visual dependencies — import analysis, not just package.json
  • Task caching: inputs + outputs in nx.json — Nx Cloud for remote cache sharing
  • libs/ for libraries, apps/ for applications — feature/ui/data/util library types
  • project.json for per-project config — nx.json for workspace-wide defaults
  • nx migrate for updates — automatic code migrations for breaking changes