> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/nrwl/nx/llms.txt
> Use this file to discover all available pages before exploring further.

# Mental model

> Understand how Nx works with project graphs, task graphs, affected commands, and caching to efficiently manage your monorepo development workflow.

Nx is a VSCode of build tools — a powerful core driven by metadata and extensible through [plugins](/concepts/nx-plugins). Everything Nx does flows from a small set of interconnected concepts: project graphs, task graphs, affected commands, computation hashing, and caching.

## The three levels of an Nx workspace

<CardGroup cols={3}>
  <Card title="Workspace" icon="folder-open">
    The root of your repository. Contains `nx.json`, one or more projects, and shared configuration.
  </Card>

  <Card title="Projects" icon="box">
    Individual applications or libraries detected by `package.json` or `project.json` files. Each project has named targets (tasks) that Nx can run.
  </Card>

  <Card title="Tasks" icon="play">
    An invocation of a target on a specific project. Running `nx build myapp` creates a single `myapp:build` task.
  </Card>
</CardGroup>

## The project graph

Nx analyzes your file system to build a **project graph** — a directed acyclic graph where nodes are projects and edges are dependencies between them.

```
app1 ──depends on──► lib
app2 ──depends on──► lib
```

Nx identifies projects by looking for `package.json` or `project.json` files. It then infers dependencies by:

* Statically analyzing TypeScript/JavaScript `import` statements
* Reading installed `node_modules` versions
* Respecting manually declared `implicitDependencies` in project configuration
* Using plugin-provided dependency detection logic

Nx caches the project graph and only re-analyzes files that have changed since the last run, keeping graph computation fast even in large repositories.

## Metadata-driven

Everything in Nx comes with metadata that enables toolability. Nx gathers information about your projects and tasks and uses that information to help you understand and interact with your codebase. With the right plugins installed, most of this metadata can be [inferred directly from your existing configuration files](/concepts/inferred-tasks) — no manual definition required.

This metadata powers:

* The Nx CLI itself
* VSCode and WebStorm integrations via [Nx Console](https://nx.dev/getting-started/editor-setup)
* GitHub PR integration
* Third-party tools built on top of Nx

## The task graph

Nx uses the project graph to construct a **task graph** for every command you run. The task graph and the project graph are related but not isomorphic — task dependencies are determined by target configuration, not purely by project dependencies.

For example, running `nx test lib` produces a task graph with a single node:

```
lib:test
```

But running `nx run-many -t test -p app1 app2 lib` produces a task graph with three nodes that can run in parallel, because testing `app1` does not depend on testing `lib` by default:

```
app1:test   (runs in parallel)
app2:test   (runs in parallel)
lib:test    (runs in parallel)
```

Now consider a `test` target that declares it depends on `^test` (test of all dependencies):

```json title="apps/app1/project.json" theme={null}
{
  "test": {
    "executor": "@nx/jest:jest",
    "outputs": ["{workspaceRoot}/coverage/apps/app1"],
    "dependsOn": ["^test"],
    "options": {
      "jestConfig": "apps/app1/jest.config.js",
      "passWithNoTests": true
    }
  }
}
```

With this configuration, the same command produces a different task graph where `lib:test` must complete before `app1:test` and `app2:test` can start:

```
lib:test
  └──► app1:test
  └──► app2:test
```

Nx executes as many tasks in parallel as constraints allow, maximizing throughput.

## Affected commands

As your workspace grows, running every task in the repository on every CI run becomes too slow. Nx solves this with the `affected` command, which performs code-change analysis to compute the minimum set of projects that could be impacted by your changes.

When you run `nx affected -t test`, Nx:

1. Looks at the files changed in your PR (compared to the base branch)
2. Determines which projects own those files
3. Walks the project graph to find all downstream dependents
4. Runs `nx run-many -t test` for only that set of projects

For example, if your PR changes `lib`, and `app1` and `app2` both depend on `lib`, Nx runs:

```bash theme={null}
nx run-many -t test -p app1 app2 lib
```

Nx also understands the nature of changes. Updating the version of `next` in `package.json` only affects projects that use Next.js — not every project in the repo.

## Computation hashing and caching

Before running any cacheable task, Nx computes a **computation hash** based on:

* All source files of the project and its dependencies
* Relevant global configuration (e.g., `nx.json`, `tsconfig.base.json`)
* Versions of external dependencies
* Runtime values such as the Node.js version
* CLI command flags

If a matching hash exists in the local cache (`.nx/cache`) or the remote cache (Nx Cloud), Nx replays the result — restoring output files and printing terminal output — without running the task. From the user's perspective, the command ran the same, only much faster.

If no match is found, Nx runs the task and stores its outputs for future use.

<Tip>
  See [How Caching Works](/concepts/how-caching-works) for a complete description of hash inputs, cache storage, and configuration options.
</Tip>

## Distributed task execution

For large workspaces, even aggressive caching may not be enough to keep CI fast. [Nx Agents](https://nx.dev/features/ci-features/distribute-task-execution) distribute the task graph across multiple machines. Tasks run in parallel across agents, sharing artifacts through remote caching. From your CI configuration's perspective, results appear as if everything ran on a single machine.

## Summary

<AccordionGroup>
  <Accordion title="Nx builds a project graph by analyzing your source code">
    Projects are detected from `package.json` and `project.json` files. Dependencies are inferred from import statements, installed packages, and plugin logic. The graph is cached and incrementally updated.
  </Accordion>

  <Accordion title="Nx creates a task graph from the project graph for every command">
    Tasks declare dependencies via `dependsOn` in target configuration. The task graph determines execution order and parallelism. The project graph and task graph are related but not identical.
  </Accordion>

  <Accordion title="Nx uses affected analysis to run only what's needed">
    Changed files map to affected projects via the project graph. Only those projects and their dependents have their tasks run.
  </Accordion>

  <Accordion title="Nx caches task results and replays them when inputs haven't changed">
    The cache key is a hash of all inputs. Cache hits restore output files and terminal output. The cache can be local, remote, or both.
  </Accordion>
</AccordionGroup>
