Skip to main content Configure and optimize Nx monorepo workspaces. Use when setting up Nx, configuring project boundaries, optimizing build caching, or implementing affected commands.
npx skills add sickn33/antigravity-awesome-skills --skill nx-workspace-patterns agentic-skills ai-agents antigravity claude-code mcp ai-workflows
Nx Workspace Patterns
Production patterns for Nx monorepo management.
Do not use this skill when
The task is unrelated to nx workspace patterns
You need a different domain or tool outside this scope
Instructions
Clarify goals, constraints, and required inputs.
Apply relevant best practices and validate outcomes.
Provide actionable steps and verification.
If detailed examples are required, open resources/implementation-playbook.md.
Use this skill when
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-authui Presentational components ui-buttonsdata-access API calls, state management data-access-usersutil Pure functions, helpers util-formattingshell App bootstrapping shell-web
Templates
Template 1: nx.json Configuration {
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"npmScope": "myorg",
"affected": {
"defaultBase": "main"
},
"tasksRunnerOptions": {
"default": {
"runner": "nx/tasks-runners/default",
"options": {
"cacheableOperations": [
"build",
"lint",
"test",
"e2e",
"build-storybook"
],
"parallel": 3
}
}
},
"targetDefaults": {
"build": {
"dependsOn": ["^build"],
"inputs": ["production", "^production"],
"cache": true
},
"test": {
"inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"],
"cache": true
},
"lint": {
"inputs": ["default", "{workspaceRoot}/.eslintrc.json"],
"cache": true
},
"e2e": {
"inputs": ["default", "^production"],
"cache": true
}
},
"namedInputs": {
"default": ["{projectRoot}/**/*", "sharedGlobals"],
"production": [
"default",
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
"!{projectRoot}/tsconfig.spec.json",
"!{projectRoot}/jest.config.[jt]s",
"!{projectRoot}/.eslintrc.json"
],
"sharedGlobals": [
"{workspaceRoot}/babel.config.json",
"{workspaceRoot}/tsconfig.base.json"
]
},
"generators": {
"@nx/react": {
"application": {
"style": "css",
"linter": "eslint",
"bundler": "webpack"
},
"library": {
"style": "css",
"linter": "eslint"
},
"component": {
"style": "css"
}
}
}
}
Template 2: Project Configuration // apps/web/project.json
{
"name": "web",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/web/src",
"projectType": "application",
"tags": ["type:app", "scope:web"],
"targets": {
"build": {
"executor": "@nx/webpack:webpack",
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "production",
"options": {
"compiler": "babel",
"outputPath": "dist/apps/web",
"index": "apps/web/src/index.html",
"main": "apps/web/src/main.tsx",
"tsConfig": "apps/web/tsconfig.app.json",
"assets": ["apps/web/src/assets"],
"styles": ["apps/web/src/styles.css"]
},
"configurations": {
"development": {
"extractLicenses": false,
"optimization": false,
"sourceMap": true
},
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractLicenses": true
}
}
},
"serve": {
"executor": "@nx/webpack:dev-server",
"defaultConfiguration": "development",
"options": {
"buildTarget": "web:build"
},
"configurations": {
"development": {
"buildTarget": "web:build:development"
},
"production": {
"buildTarget": "web:build:production"
}
}
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "apps/web/jest.config.ts",
"passWithNoTests": true
}
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/web/**/*.{ts,tsx,js,jsx}"]
}
}
}
}
Template 3: Module Boundary Rules // .eslintrc.json
{
"root": true,
"ignorePatterns": ["**/*"],
"plugins": ["@nx"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {
"@nx/enforce-module-boundaries": [
"error",
{
"enforceBuildableLibDependency": true,
"allow": [],
"depConstraints": [
{
"sourceTag": "type:app",
"onlyDependOnLibsWithTags": [
"type:feature",
"type:ui",
"type:data-access",
"type:util"
]
},
{
"sourceTag": "type:feature",
"onlyDependOnLibsWithTags": [
"type:ui",
"type:data-access",
"type:util"
]
},
{
"sourceTag": "type:ui",
"onlyDependOnLibsWithTags": ["type:ui", "type:util"]
},
{
"sourceTag": "type:data-access",
"onlyDependOnLibsWithTags": ["type:data-access", "type:util"]
},
{
"sourceTag": "type:util",
"onlyDependOnLibsWithTags": ["type:util"]
},
{
"sourceTag": "scope:web",
"onlyDependOnLibsWithTags": ["scope:web", "scope:shared"]
},
{
"sourceTag": "scope:api",
"onlyDependOnLibsWithTags": ["scope:api", "scope:shared"]
},
{
"sourceTag": "scope:shared",
"onlyDependOnLibsWithTags": ["scope:shared"]
}
]
}
]
}
}
]
}
Template 4: Custom Generator // tools/generators/feature-lib/index.ts
import {
Tree,
formatFiles,
generateFiles,
joinPathFragments,
names,
readProjectConfiguration,
} from '@nx/devkit';
import { libraryGenerator } from '@nx/react';
interface FeatureLibraryGeneratorSchema {
name: string;
scope: string;
directory?: string;
}
export default async function featureLibraryGenerator(
tree: Tree,
options: FeatureLibraryGeneratorSchema
) {
const { name, scope, directory } = options;
const projectDirectory = directory
? `${directory}/${name}`
: `libs/${scope}/feature-${name}`;
// Generate base library
await libraryGenerator(tree, {
name: `feature-${name}`,
directory: projectDirectory,
tags: `type:feature,scope:${scope}`,
style: 'css',
skipTsConfig: false,
skipFormat: true,
unitTestRunner: 'jest',
linter: 'eslint',
});
// Add custom files
const projectConfig = readProjectConfiguration(tree, `${scope}-feature-${name}`);
const projectNames = names(name);
generateFiles(
tree,
joinPathFragments(__dirname, 'files'),
projectConfig.sourceRoot,
{
...projectNames,
scope,
tmpl: '',
}
);
await formatFiles(tree);
}
Template 5: CI Configuration with Affected # .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
jobs:
main:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Derive SHAs for affected commands
uses: nrwl/nx-set-shas@v4
- name: Run affected lint
run: npx nx affected -t lint --parallel=3
- name: Run affected test
run: npx nx affected -t test --parallel=3 --configuration=ci
- name: Run affected build
run: npx nx affected -t build --parallel=3
- name: Run affected e2e
run: npx nx affected -t e2e --parallel=1
Template 6: Remote Caching Setup // nx.json with Nx Cloud
{
"tasksRunnerOptions": {
"default": {
"runner": "nx-cloud",
"options": {
"cacheableOperations": ["build", "lint", "test", "e2e"],
"accessToken": "your-nx-cloud-token",
"parallel": 3,
"cacheDirectory": ".nx/cache"
}
}
},
"nxCloudAccessToken": "your-nx-cloud-token"
}
// Self-hosted cache with S3
{
"tasksRunnerOptions": {
"default": {
"runner": "@nx-aws-cache/nx-aws-cache",
"options": {
"cacheableOperations": ["build", "lint", "test"],
"awsRegion": "us-east-1",
"awsBucket": "my-nx-cache-bucket",
"awsProfile": "default"
}
}
}
}
Common Commands # Generate new library
nx g @nx/react:lib feature-auth --directory=libs/web --tags=type:feature,scope:web
# Run affected tests
nx affected -t test --base=main
# View dependency graph
nx graph
# Run specific project
nx build web --configuration=production
# Reset cache
nx reset
# Run migrations
nx migrate latest
nx 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
Limitations
Use this skill only when the task clearly matches the scope described above.
Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Set up and use 1Password CLI (op). Use when installing the CLI, enabling desktop app integration, signing in (single or multi-account), or reading/injecting/running secrets via op.
CLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Set up and use 1Password CLI (op). Use when installing the CLI, enabling desktop app integration, signing in (single or multi-account), or reading/injecting/running secrets via op.
CLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).