# Pin Node version with nvm and .nvmrc

- Status: accepted
- Date: 2026-04-26

## Context and Problem Statement

Angular 18 requires Node.js `^18.19.1 || ^20.11.1`. The system Node version on a development machine may not meet this requirement, causing silent build failures or CLI errors. How should the required Node version be enforced?

## Considered Options

- nvm with `.nvmrc`
- System Node (no version management)
- Other version managers (fnm, volta)

## Decision Outcome

Chosen option: "nvm with `.nvmrc`", because it pins the version explicitly in the repository, is already in use on the development machine, and integrates directly with the Husky pre-commit hook.

A `.nvmrc` file at the repository root pins Node to `20.19.6`. The Husky pre-commit hook explicitly calls `nvm use 20.19.6` before running tests to ensure the correct version is active in the hook's shell environment.

### Positive Consequences

- Consistent Node version across all commands: dev server, build, tests, pre-commit hook.
- `.nvmrc` documents the required Node version explicitly in the repository.

### Negative Consequences

- Requires nvm. Developers using other version managers (fnm, volta) must align manually.

## Pros and Cons of the Options

### nvm with `.nvmrc`

- Good, because explicit version pinning visible in the repository.
- Good, because integrates with Husky hook via `nvm use`.
- Bad, because tied to nvm — other version managers need manual alignment.

### System Node

- Good, because no tooling required.
- Bad, because version is not pinned — any system upgrade can silently break the build.

### Other version managers (fnm, volta)

- Good, because faster and more ergonomic than nvm for some workflows.
- Bad, because not the currently installed tool — switching would require migration.

## Links

- The `package.json` `engines` field (`^18.19.1 || ^20.11.1`) provides a secondary signal for tooling that reads it.
