Configure an Nx workspace
Nx is a build system for monorepos that adds computation caching, dependency-graph-aware task scheduling, and code generation on top of your existing toolchain. The root nx.json controls all of it — which targets are cacheable, how tasks sequence across the project graph, and exactly which file changes invalidate a cached result. This builder generates a correct, modern nx.json from your settings.
The key sections of nx.json
targetDefaults
targetDefaults defines shared configuration for a target name across every project in the workspace. Instead of specifying build settings in each project’s project.json, you write them once here and every project inherits them:
{
"targetDefaults": {
"build": {
"dependsOn": ["^build"],
"inputs": ["production", "^production"],
"outputs": ["{projectRoot}/dist"],
"cache": true
},
"test": {
"inputs": ["default", "^default"],
"cache": true
},
"lint": {
"inputs": ["default", "^default"],
"cache": true
}
}
}
Individual project.json files can override or extend these defaults as needed.
The ^ caret in dependsOn
A ^ prefix like "^build" means “run build in all projects that this project depends on before running build here”. Without the caret, the dependency refers to another target on the same project. The caret is what turns a flat list of tasks into a depth-first graph traversal that matches your library dependency order.
namedInputs
namedInputs defines reusable file-glob sets that feed the computation hash:
{
"namedInputs": {
"default": ["{projectRoot}/**/*", "sharedGlobals"],
"production": ["default", "!{projectRoot}/**/*.spec.ts", "!{projectRoot}/jest.config.ts"]
}
}
The production named input excludes test files and test config. This means editing a *.spec.ts file invalidates the test cache (because test uses default) but does not invalidate the build cache (because build uses production). Without this separation, every spec edit would bust your build cache unnecessarily.
Outputs: the most common misconfiguration
outputs tells Nx which directories to save when a cache entry is written and which to restore on a cache hit. An incorrect path means Nx records a cache hit but restores nothing:
"outputs": ["{projectRoot}/dist"]
Check that {projectRoot}/dist (or wherever your tool writes its output) matches what the actual tool produces. TypeScript projects often write to a dist directory relative to the package; bundlers like webpack or vite may write to build or out.
Parallelism
{
"parallel": 4
}
Set parallel to approximately the number of CPU cores available. Nx defaults to 3 if not specified. On a build server with more cores, raising this value is one of the easiest throughput wins. The explicit tasksRunnerOptions form is only needed if you are using a custom or legacy runner that requires it.
What a minimal working nx.json looks like
{
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"namedInputs": {
"default": ["{projectRoot}/**/*", "sharedGlobals"],
"production": ["default", "!{projectRoot}/**/*.spec.ts"]
},
"targetDefaults": {
"build": {
"dependsOn": ["^build"],
"inputs": ["production", "^production"],
"outputs": ["{projectRoot}/dist"],
"cache": true
},
"test": { "inputs": ["default", "^default"], "cache": true },
"lint": { "inputs": ["default", "^default"], "cache": true }
},
"parallel": 4
}
Copy this into nx.json at the root of your Nx workspace, then adjust the outputs path to match your actual build output locations.