Nx Workspace Patterns

Master Nx monorepo architecture with production-ready patterns

✨ The solution you've been looking for

Verified
Tested and verified by our team
25450 Stars

Configure and optimize Nx monorepo workspaces. Use when setting up Nx, configuring project boundaries, optimizing build caching, or implementing affected commands.

nx monorepo build-optimization dependency-management ci-cd caching project-boundaries architecture
Repository

See It In Action

Interactive preview & real-world examples

Live Demo
Skill Demo Animation

AI Conversation Simulator

See how users interact with this skill

User Prompt

Help me set up an Nx workspace for a web app with API backend, including proper library organization and module boundaries

Skill Processing

Analyzing request...

Agent Response

Complete nx.json configuration, project structure, and ESLint boundary rules

Quick Start (3 Steps)

Get up and running in minutes

1

Install

claude-code skill install nx-workspace-patterns

claude-code skill install nx-workspace-patterns
2

Config

3

First Trigger

@nx-workspace-patterns help

Commands

CommandDescriptionRequired Args
@nx-workspace-patterns setting-up-nx-workspace-architectureConfigure a new Nx monorepo with proper project boundaries and library typesNone
@nx-workspace-patterns optimizing-ci-with-affected-commandsImplement efficient CI pipelines that only test and build changed projectsNone
@nx-workspace-patterns implementing-remote-cachingSet up distributed caching to speed up builds across team members and CINone

Typical Use Cases

Setting up Nx workspace architecture

Configure a new Nx monorepo with proper project boundaries and library types

Optimizing CI with affected commands

Implement efficient CI pipelines that only test and build changed projects

Implementing remote caching

Set up distributed caching to speed up builds across team members and CI

Overview

Nx Workspace Patterns

Production patterns for Nx monorepo management.

When to Use This Skill

  • Setting up new Nx workspaces
  • Configuring project boundaries
  • Optimizing CI with affected commands
  • Implementing remote caching
  • Managing dependencies between projects
  • Migrating to Nx

Core Concepts

1. Nx Architecture

workspace/
├── apps/              # Deployable applications
│   ├── web/
│   └── api/
├── libs/              # Shared libraries
│   ├── shared/
│   │   ├── ui/
│   │   └── utils/
│   └── feature/
│       ├── auth/
│       └── dashboard/
├── tools/             # Custom executors/generators
├── nx.json            # Nx configuration
└── workspace.json     # Project configuration

2. Library Types

TypePurposeExample
featureSmart components, business logicfeature-auth
uiPresentational componentsui-buttons
data-accessAPI calls, state managementdata-access-users
utilPure functions, helpersutil-formatting
shellApp bootstrappingshell-web

Templates

Template 1: nx.json Configuration

 1{
 2  "$schema": "./node_modules/nx/schemas/nx-schema.json",
 3  "npmScope": "myorg",
 4  "affected": {
 5    "defaultBase": "main"
 6  },
 7  "tasksRunnerOptions": {
 8    "default": {
 9      "runner": "nx/tasks-runners/default",
10      "options": {
11        "cacheableOperations": [
12          "build",
13          "lint",
14          "test",
15          "e2e",
16          "build-storybook"
17        ],
18        "parallel": 3
19      }
20    }
21  },
22  "targetDefaults": {
23    "build": {
24      "dependsOn": ["^build"],
25      "inputs": ["production", "^production"],
26      "cache": true
27    },
28    "test": {
29      "inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"],
30      "cache": true
31    },
32    "lint": {
33      "inputs": ["default", "{workspaceRoot}/.eslintrc.json"],
34      "cache": true
35    },
36    "e2e": {
37      "inputs": ["default", "^production"],
38      "cache": true
39    }
40  },
41  "namedInputs": {
42    "default": ["{projectRoot}/**/*", "sharedGlobals"],
43    "production": [
44      "default",
45      "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
46      "!{projectRoot}/tsconfig.spec.json",
47      "!{projectRoot}/jest.config.[jt]s",
48      "!{projectRoot}/.eslintrc.json"
49    ],
50    "sharedGlobals": [
51      "{workspaceRoot}/babel.config.json",
52      "{workspaceRoot}/tsconfig.base.json"
53    ]
54  },
55  "generators": {
56    "@nx/react": {
57      "application": {
58        "style": "css",
59        "linter": "eslint",
60        "bundler": "webpack"
61      },
62      "library": {
63        "style": "css",
64        "linter": "eslint"
65      },
66      "component": {
67        "style": "css"
68      }
69    }
70  }
71}

Template 2: Project Configuration

 1// apps/web/project.json
 2{
 3  "name": "web",
 4  "$schema": "../../node_modules/nx/schemas/project-schema.json",
 5  "sourceRoot": "apps/web/src",
 6  "projectType": "application",
 7  "tags": ["type:app", "scope:web"],
 8  "targets": {
 9    "build": {
10      "executor": "@nx/webpack:webpack",
11      "outputs": ["{options.outputPath}"],
12      "defaultConfiguration": "production",
13      "options": {
14        "compiler": "babel",
15        "outputPath": "dist/apps/web",
16        "index": "apps/web/src/index.html",
17        "main": "apps/web/src/main.tsx",
18        "tsConfig": "apps/web/tsconfig.app.json",
19        "assets": ["apps/web/src/assets"],
20        "styles": ["apps/web/src/styles.css"]
21      },
22      "configurations": {
23        "development": {
24          "extractLicenses": false,
25          "optimization": false,
26          "sourceMap": true
27        },
28        "production": {
29          "optimization": true,
30          "outputHashing": "all",
31          "sourceMap": false,
32          "extractLicenses": true
33        }
34      }
35    },
36    "serve": {
37      "executor": "@nx/webpack:dev-server",
38      "defaultConfiguration": "development",
39      "options": {
40        "buildTarget": "web:build"
41      },
42      "configurations": {
43        "development": {
44          "buildTarget": "web:build:development"
45        },
46        "production": {
47          "buildTarget": "web:build:production"
48        }
49      }
50    },
51    "test": {
52      "executor": "@nx/jest:jest",
53      "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
54      "options": {
55        "jestConfig": "apps/web/jest.config.ts",
56        "passWithNoTests": true
57      }
58    },
59    "lint": {
60      "executor": "@nx/eslint:lint",
61      "outputs": ["{options.outputFile}"],
62      "options": {
63        "lintFilePatterns": ["apps/web/**/*.{ts,tsx,js,jsx}"]
64      }
65    }
66  }
67}

Template 3: Module Boundary Rules

 1// .eslintrc.json
 2{
 3  "root": true,
 4  "ignorePatterns": ["**/*"],
 5  "plugins": ["@nx"],
 6  "overrides": [
 7    {
 8      "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
 9      "rules": {
10        "@nx/enforce-module-boundaries": [
11          "error",
12          {
13            "enforceBuildableLibDependency": true,
14            "allow": [],
15            "depConstraints": [
16              {
17                "sourceTag": "type:app",
18                "onlyDependOnLibsWithTags": [
19                  "type:feature",
20                  "type:ui",
21                  "type:data-access",
22                  "type:util"
23                ]
24              },
25              {
26                "sourceTag": "type:feature",
27                "onlyDependOnLibsWithTags": [
28                  "type:ui",
29                  "type:data-access",
30                  "type:util"
31                ]
32              },
33              {
34                "sourceTag": "type:ui",
35                "onlyDependOnLibsWithTags": ["type:ui", "type:util"]
36              },
37              {
38                "sourceTag": "type:data-access",
39                "onlyDependOnLibsWithTags": ["type:data-access", "type:util"]
40              },
41              {
42                "sourceTag": "type:util",
43                "onlyDependOnLibsWithTags": ["type:util"]
44              },
45              {
46                "sourceTag": "scope:web",
47                "onlyDependOnLibsWithTags": ["scope:web", "scope:shared"]
48              },
49              {
50                "sourceTag": "scope:api",
51                "onlyDependOnLibsWithTags": ["scope:api", "scope:shared"]
52              },
53              {
54                "sourceTag": "scope:shared",
55                "onlyDependOnLibsWithTags": ["scope:shared"]
56              }
57            ]
58          }
59        ]
60      }
61    }
62  ]
63}

Template 4: Custom Generator

 1// tools/generators/feature-lib/index.ts
 2import {
 3  Tree,
 4  formatFiles,
 5  generateFiles,
 6  joinPathFragments,
 7  names,
 8  readProjectConfiguration,
 9} from "@nx/devkit";
10import { libraryGenerator } from "@nx/react";
11
12interface FeatureLibraryGeneratorSchema {
13  name: string;
14  scope: string;
15  directory?: string;
16}
17
18export default async function featureLibraryGenerator(
19  tree: Tree,
20  options: FeatureLibraryGeneratorSchema,
21) {
22  const { name, scope, directory } = options;
23  const projectDirectory = directory
24    ? `${directory}/${name}`
25    : `libs/${scope}/feature-${name}`;
26
27  // Generate base library
28  await libraryGenerator(tree, {
29    name: `feature-${name}`,
30    directory: projectDirectory,
31    tags: `type:feature,scope:${scope}`,
32    style: "css",
33    skipTsConfig: false,
34    skipFormat: true,
35    unitTestRunner: "jest",
36    linter: "eslint",
37  });
38
39  // Add custom files
40  const projectConfig = readProjectConfiguration(
41    tree,
42    `${scope}-feature-${name}`,
43  );
44  const projectNames = names(name);
45
46  generateFiles(
47    tree,
48    joinPathFragments(__dirname, "files"),
49    projectConfig.sourceRoot,
50    {
51      ...projectNames,
52      scope,
53      tmpl: "",
54    },
55  );
56
57  await formatFiles(tree);
58}

Template 5: CI Configuration with Affected

 1# .github/workflows/ci.yml
 2name: CI
 3
 4on:
 5  push:
 6    branches: [main]
 7  pull_request:
 8    branches: [main]
 9
10env:
11  NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
12
13jobs:
14  main:
15    runs-on: ubuntu-latest
16    steps:
17      - uses: actions/checkout@v4
18        with:
19          fetch-depth: 0
20
21      - uses: actions/setup-node@v4
22        with:
23          node-version: 20
24          cache: "npm"
25
26      - name: Install dependencies
27        run: npm ci
28
29      - name: Derive SHAs for affected commands
30        uses: nrwl/nx-set-shas@v4
31
32      - name: Run affected lint
33        run: npx nx affected -t lint --parallel=3
34
35      - name: Run affected test
36        run: npx nx affected -t test --parallel=3 --configuration=ci
37
38      - name: Run affected build
39        run: npx nx affected -t build --parallel=3
40
41      - name: Run affected e2e
42        run: npx nx affected -t e2e --parallel=1

Template 6: Remote Caching Setup

 1// nx.json with Nx Cloud
 2{
 3  "tasksRunnerOptions": {
 4    "default": {
 5      "runner": "nx-cloud",
 6      "options": {
 7        "cacheableOperations": ["build", "lint", "test", "e2e"],
 8        "accessToken": "your-nx-cloud-token",
 9        "parallel": 3,
10        "cacheDirectory": ".nx/cache"
11      }
12    }
13  },
14  "nxCloudAccessToken": "your-nx-cloud-token"
15}
16
17// Self-hosted cache with S3
18{
19  "tasksRunnerOptions": {
20    "default": {
21      "runner": "@nx-aws-cache/nx-aws-cache",
22      "options": {
23        "cacheableOperations": ["build", "lint", "test"],
24        "awsRegion": "us-east-1",
25        "awsBucket": "my-nx-cache-bucket",
26        "awsProfile": "default"
27      }
28    }
29  }
30}

Common Commands

 1# Generate new library
 2nx g @nx/react:lib feature-auth --directory=libs/web --tags=type:feature,scope:web
 3
 4# Run affected tests
 5nx affected -t test --base=main
 6
 7# View dependency graph
 8nx graph
 9
10# Run specific project
11nx build web --configuration=production
12
13# Reset cache
14nx reset
15
16# Run migrations
17nx migrate latest
18nx migrate --run-migrations

Best Practices

Do’s

  • Use tags consistently - Enforce with module boundaries
  • Enable caching early - Significant CI savings
  • Keep libs focused - Single responsibility
  • Use generators - Ensure consistency
  • Document boundaries - Help new developers

Don’ts

  • Don’t create circular deps - Graph should be acyclic
  • Don’t skip affected - Test only what changed
  • Don’t ignore boundaries - Tech debt accumulates
  • Don’t over-granularize - Balance lib count

Resources

What Users Are Saying

Real feedback from the community

Environment Matrix

Dependencies

Node.js 16+
npm or yarn
Nx CLI

Framework Support

React ✓ (recommended) Angular ✓ Vue ✓ Next.js ✓ Express ✓ NestJS ✓

Context Window

Token Usage ~3K-8K tokens for workspace configurations

Security & Privacy

Information

Author
wshobson
Updated
2026-01-30
Category
automation-tools