Nx Workspace Patterns
Master Nx monorepo architecture with production-ready patterns
✨ The solution you've been looking for
Configure and optimize Nx monorepo workspaces. Use when setting up Nx, configuring project boundaries, optimizing build caching, or implementing affected commands.
See It In Action
Interactive preview & real-world examples
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
Install
claude-code skill install nx-workspace-patterns
claude-code skill install nx-workspace-patternsConfig
First Trigger
@nx-workspace-patterns helpCommands
| Command | Description | Required Args |
|---|---|---|
| @nx-workspace-patterns setting-up-nx-workspace-architecture | Configure a new Nx monorepo with proper project boundaries and library types | None |
| @nx-workspace-patterns optimizing-ci-with-affected-commands | Implement efficient CI pipelines that only test and build changed projects | None |
| @nx-workspace-patterns implementing-remote-caching | Set up distributed caching to speed up builds across team members and CI | None |
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
| Type | Purpose | Example |
|---|---|---|
| feature | Smart components, business logic | feature-auth |
| ui | Presentational components | ui-buttons |
| data-access | API calls, state management | data-access-users |
| util | Pure functions, helpers | util-formatting |
| shell | App bootstrapping | shell-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
Framework Support
Context Window
Security & Privacy
Information
- Author
- wshobson
- Updated
- 2026-01-30
- Category
- automation-tools
Related Skills
Nx Workspace Patterns
Configure and optimize Nx monorepo workspaces. Use when setting up Nx, configuring project …
View Details →Monorepo Management
Master monorepo management with Turborepo, Nx, and pnpm workspaces to build efficient, scalable …
View Details →Monorepo Management
Master monorepo management with Turborepo, Nx, and pnpm workspaces to build efficient, scalable …
View Details →