|$ curl https://forge-ai.dev/api/markdown?path=docs/build-tools/nx
$cat docs/nx.md
updated Today·26-34 min read·published

Nx

Build ToolsNxMonorepoIntermediate to Advanced🎯Free Tools
Introduction

Nx is a smart monorepo toolkit: project graph analysis, task running with computation caching, code generators, and optional module boundary rules. Like Turborepo, it orchestrates builds — unlike Turborepo, it also shapes how teams create and constrain packages.

Use Nx when structure and scale matter as much as cache hits. Use Turborepo when you mainly need a fast pipeline on an existing workspace. Use pnpm workspaces alone when the repo is small and CI is already fast.

info

Nx can wrap Vite, Webpack, esbuild, Next.js, and more via executors/plugins. You still choose per-app bundlers; Nx schedules them.
Core Concepts
ConceptWhat it isWhy it matters
Project graphNodes = projects; edges = imports/depsEnables affected & ordering
TargetsNamed tasks (build, test, lint)Consistent CLI across packages
Executors / pluginsHow a target runsIntegrates Vite/Jest/etc.
GeneratorsScaffold apps/libs/filesOrg-standard structure
CacheLocal + optional remoteSkip unchanged work
Setup
setup.sh
Bash
1# New Nx workspace
2npx create-nx-workspace@latest acme --preset=apps
3
4# Add Nx to an existing pnpm/npm monorepo
5npx nx@latest init
6
7# Common plugins
8npx nx add @nx/vite
9npx nx add @nx/next
10npx nx add @nx/js
11npx nx add @nx/eslint
nx.json (sketch)
JSON
1{
2 "$schema": "./node_modules/nx/schemas/nx-schema.json",
3 "targetDefaults": {
4 "build": {
5 "dependsOn": ["^build"],
6 "inputs": ["production", "^production"],
7 "cache": true
8 },
9 "test": {
10 "inputs": ["default", "^production"],
11 "cache": true
12 },
13 "lint": {
14 "cache": true
15 }
16 },
17 "namedInputs": {
18 "default": ["{projectRoot}/**/*", "sharedGlobals"],
19 "production": [
20 "default",
21 "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
22 "!{projectRoot}/tsconfig.spec.json"
23 ],
24 "sharedGlobals": ["{workspaceRoot}/tsconfig.base.json"]
25 }
26}
Project Graph

Nx analyzes TypeScript imports and package dependencies to build a graph. Visualize it when debugging unexpected rebuilds or illegal imports.

graph.sh
Bash
1# Interactive graph in the browser
2npx nx graph
3
4# JSON for tooling
5npx nx graph --file=graph.json
6
7# Focus on one project
8npx nx graph --focus=web
📝

note

If the graph is wrong, check path aliases in tsconfig.base.json and whether packages use workspace protocol dependencies correctly.
Affected Commands

nx affected runs targets only for projects impacted by a git diff — the killer feature for large monorepo CI.

affected.sh
Bash
1# Compare against main
2npx nx affected -t build --base=origin/main --head=HEAD
3
4# Multiple targets
5npx nx affected -t lint,test,build --base=origin/main
6
7# Print projects without running
8npx nx show projects --affected --base=origin/main
9
10# CI example: shallow clones need fetch-depth: 0 for accurate base
Change typeTypically affectsCI impact
Leaf app onlyThat app (+ maybe e2e)Minimal
Shared UI libAll dependent appsMedium–large
Root tooling (eslint)Many projectsBroad — expect it
Caching

Nx hashes inputs defined by namedInputsand target configuration. Remote caching (Nx Cloud or self-hosted) mirrors Turborepo's remote cache value proposition.

cache.sh
Bash
1# Run with cache
2npx nx run web:build
3
4# Skip cache
5npx nx run web:build --skip-nx-cache
6
7# Reset local cache
8npx nx reset

warning

Configure inputs carefully. If production builds embed env vars not listed as inputs, you can ship the wrong cached artifact.
Generators

Generators scaffold consistent apps and libraries. Publish workspace generators so feature teams cannot invent one-off folder layouts.

generators.sh
Bash
1# Official examples
2npx nx g @nx/react:library ui-button --directory=libs/ui/button
3npx nx g @nx/js:lib utils --bundler=tsc
4npx nx g @nx/vite:app web
5
6# List available generators
7npx nx list
8npx nx list @nx/react

best practice

Codify org standards (tags, lint rules, test setup) inside custom generators. Documentation alone drifts; generators enforce structure at creation time.
Module Boundaries

Tag projects (scope:shared, type:feature, type:util) and enforce legal dependency directions with @nx/enforce-module-boundaries.

eslint.config.mjs (sketch)
JavaScript
1import nxPlugin from "@nx/eslint-plugin";
2
3export default [
4 {
5 plugins: { "@nx": nxPlugin },
6 rules: {
7 "@nx/enforce-module-boundaries": [
8 "error",
9 {
10 enforceBuildableLibDependency: true,
11 allow: [],
12 depConstraints: [
13 {
14 sourceTag: "type:app",
15 onlyDependOnProjectsWithTags: ["type:feature", "type:ui", "type:util"],
16 },
17 {
18 sourceTag: "type:feature",
19 onlyDependOnProjectsWithTags: ["type:ui", "type:util", "type:data"],
20 },
21 {
22 sourceTag: "type:util",
23 onlyDependOnProjectsWithTags: ["type:util"],
24 },
25 ],
26 },
27 ],
28 },
29 },
30];
Rule ideaWhyViolation smell
utils cannot import featuresKeep low-level packages pureCircular domain coupling
apps cannot import other appsForce shared code into libsCopy-paste across apps
scope:admin ≠ scope:publicSecurity / product isolationAdmin code in public bundle
Nx vs Turborepo vs pnpm Alone
ChooseWhenYou accept
pnpm workspaces onlyFew packages (about 5 or fewer), simple scriptsManual ordering, no remote task cache
TurborepoNeed cache/pipelines fast with low ceremonyDIY structure & boundaries
NxNeed affected, generators, boundaries, pluginsMore concepts & config
🔥

pro tip

These tools are not mutually exclusive forever — but pick one orchestrator as source of truth. Running both Nx and Turborepo for the same tasks doubles complexity.
CI Pattern
.github/workflows/ci.yml
YAML
1name: CI
2on: [pull_request]
3jobs:
4 main:
5 runs-on: ubuntu-latest
6 steps:
7 - uses: actions/checkout@v4
8 with:
9 fetch-depth: 0
10 - uses: pnpm/action-setup@v4
11 - uses: actions/setup-node@v4
12 with:
13 node-version: 22
14 cache: pnpm
15 - run: pnpm install --frozen-lockfile
16 - run: pnpm nx affected -t lint,test,build --base=origin/main --parallel=3
Adoption Guidance
  • Start with nx init on an existing repo before a full rewrite.
  • Introduce tags + boundaries gradually — warn first, then error.
  • Standardize generators after the third copy-pasted library.
  • Measure CI with affected + remote cache before buying more runners.
📝

note

Nx shines at organizational scale. For a weekend side project monorepo, Turborepo or plain pnpm is usually enough.
$Blueprint — Engineering Documentation·Section ID: BT-NX-01·Revision: 1.0

Community

Get help on Slack, Discord or VIP

Stuck on a guide? Join the community and ask.