Think of Nx as a coordinator for the tools in your workspace. Vite, Jest, and other tools still do their own work, while Nx maps how projects and tasks relate and then decides what to run, in what order, and whether previous work can be reused.
The project graph
Section titled “The project graph”The project graph represents projects in your workspace and the dependencies between them. It also includes external dependencies, such as Vite, React, and Angular.
Nx plugins identify projects from files such as package.json, project.json, and tool configuration files. Nx then analyzes source code, TypeScript configuration, and package dependencies to find the connections between projects. You can add dependencies manually when Nx can't determine them from the workspace.
Nx caches the project graph and recomputes the parts affected by file changes. The updated graph reflects the current state of your workspace.
Metadata-driven
Section titled “Metadata-driven”Nx combines project configuration with metadata inferred by plugins. For example, the @nx/vite plugin can infer tasks from a project's vite.config.ts file, including commands, cache inputs, and outputs.
Nx, Nx Console, coding agents, and other integrations use this metadata to understand and interact with your workspace.

The task graph
Section titled “The task graph”Nx creates a task graph whenever you run tasks. Each node is a task, which is a specific target invoked for a project, such as myapp:build. Edges represent the dependencies between tasks. For example, nx test lib creates a task graph with one node:
The project graph and task graph aren't identical. In this project graph, both applications depend on lib:
Running nx run-many -t test -p app1 app2 lib creates three independent tasks because the task pipeline doesn't define dependencies between the test targets:
Without task dependencies, Nx can run all three test tasks in parallel.
Builds commonly need a different relationship because an application may consume the built output of its libraries. Use dependsOn to make each build task depend on the build tasks of its project dependencies:
{ "targetDefaults": { "build": { "dependsOn": ["^build"], }, },}Running nx run-many -t build -p app1 app2 lib now produces task dependencies that follow the project graph:
With this rule, app1:build and app2:build wait for lib:build. After lib:build completes, Nx can run both application builds in parallel.
For more information, see task pipeline configuration.
Affected commands
Section titled “Affected commands”Running nx test app1 creates the app1:test task and any tasks it depends on. Running nx run-many -t test -p app1 lib creates tasks for both projects. Without a project filter, nx run-many -t test creates a test task for every project with that target.
Use nx affected -t test to limit the task graph to projects affected by your changes. Nx maps changed files to projects, applies plugin-specific change analysis, and follows the project graph to include dependent projects. It then runs the requested target for that set.
For example, if a change affects lib, and both app1 and app2 depend on it, the affected project set contains all three projects.
For more information, see affected tasks.
Computation hashing and caching
Section titled “Computation hashing and caching”Before running a cacheable task, Nx hashes its inputs. These inputs can include source files, configuration, dependencies, runtime values, and command-line arguments. If the hash matches a previous run, Nx restores the cached terminal output and file artifacts instead of running the task again.
Nx checks the local cache first and then checks the remote cache when one is configured. A cache hit has the same result as executing the task, but avoids the computation.
For the complete hashing and cache model, see how caching works.
Distributed task execution
Section titled “Distributed task execution”A single machine eventually limits how many tasks you can run in parallel. Nx Agents distribute the task graph across multiple machines while preserving its dependency order. Agents use remote caching to share task artifacts, so a dependent task can use output produced on a different machine.