# How to install Node.js This guide shows how to get `node` and `npm` onto a machine, install the language server beside them, and check that Turbo JS finds it. It assumes you already have Turbo JS, or are about to — see [how to install the editor](install.md) for that. **The editor works without any of this.** Editing, colouring, themes, snippets and terminal windows all run with no Node at all. What needs it is every command in the JavaScript menu, and — through the language server — completion, the Code menu and the error marks in the gutter. ## Which pieces you need | Piece | What it is for | Comes from | | --- | --- | --- | | `node` | The runtime: runs scripts, and is also the test runner (`node --test`) and a syntax checker (`node --check`) | the Node.js installer or a version manager | | `npm` | The package manager: installs a project's dependencies and, with `-g`, tools such as the language server | ships with Node | | `npx` | Runs a tool from the project's dependencies, or downloads it into a cache first — how the starter file runs Prettier and ESLint | ships with npm | | `typescript-language-server` + `typescript@6` | The language server, and the engine it wraps | `npm install -g` | Turbo JS was written against Node **24** and npm **11**; any current release works. ## Install Node Pick one. A version manager is the usual choice on a machine where more than one project lives, because projects pin different Node versions. **With nvm** (macOS and Linux): ```bash curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash exec $SHELL nvm install --lts ``` **With Volta:** ```bash curl https://get.volta.sh | bash exec $SHELL volta install node ``` **With Homebrew** (macOS): ```bash brew install node ``` **With the installer** from [nodejs.org](https://nodejs.org), which puts `node` and `npm` in `/usr/local/bin` on macOS and Linux. Check: ```bash node --version npm --version ``` ``` v24.19.0 11.17.0 ``` ## Install the language server ```bash npm install -g typescript-language-server typescript@6 ``` Two packages. The `@6` is not optional: TypeScript 7 is the native port and ships no `tsserver.js`, and the server refuses to start beside it. [How to enable completion](enable-completion.md) says more. Turbo JS's own installer will do this when asked: ```bash scripts/install.sh --with-server ``` It runs the same `npm install -g` when no working server is found, and needs `npm` on `PATH`. ## Check it ```bash typescript-language-server --version ``` ``` 6.0.0 ``` And that it really starts — a server whose TypeScript is the wrong version fails only at this point, not at `--version`: ```bash echo | typescript-language-server --stdio ``` It reads an empty line, finds no message in it, and exits quietly. A server that prints *Could not find a valid TypeScript installation* has TypeScript 7 beside it: `npm install -g typescript@6`. ## Check that the editor finds it Open any `.js` file inside a project and read the right-hand end of the status bar: ``` F1 Describe F2 Save F3 Open F6 Window F10 Menu 1:1 LSP: ready ``` `LSP: ready` means the server started. `LSP: no typescript-language-server — npm install -g typescript-language-server typescript@6` means it was not found, and the message says how to get it. **Turbo JS looks in these places, in order**: your `PATH`; `$NVM_BIN`, the directory of the Node version nvm has selected; `$NPM_CONFIG_PREFIX/bin`, or `~/.npm-global/bin` when that variable is unset; `$PNPM_HOME`; `$VOLTA_HOME/bin`, or `~/.volta/bin`; then `/usr/local/bin` and `/opt/homebrew/bin`. The version-manager directories are searched even when they are not on `PATH` — an editor started from a desktop launcher, say — so that the case that otherwise looks like the server being broken works. ## Variants - **`npm install -g` asks for sudo.** Node from the system installer owns `/usr/local/lib`. Either use `sudo`, or give npm a prefix of your own: `npm config set prefix ~/.npm-global` and add `~/.npm-global/bin` to `PATH` — the editor searches that directory by name. - **You use pnpm.** `pnpm add -g typescript-language-server typescript@6` puts the server in `$PNPM_HOME`, which the editor searches. - **You already have `typescript-language-server` but no completion.** Run `echo | typescript-language-server --stdio` and read what it says. Then read the status bar — `Run ▸ Language server status` shows the path the editor found and whether the server answered its handshake. - **You want to upgrade.** `npm update -g typescript-language-server`. Keep `typescript` on 6 until the server can start with 7. Restart the editor: it starts one server per session and does not notice a new binary until then. - **You are installing for CI, or into an image.** `node:24-alpine` and the other official images carry `node`, `npm` and `npx`; `npm install -g typescript-language-server typescript@6` in a `RUN` line adds the server. The editor cannot use a server inside a container, so this is for running the project's commands, not for completion. - **You want to be sure the editor is not simply finding it on `PATH`.** Start it with a stripped environment — `env PATH=/usr/bin:/bin turbo-js main.js` — and the status bar should still say `LSP: ready` from one of the directories above. ## What each piece is for, from the editor's side | Piece | What the editor uses it for | | --- | --- | | `typescript-language-server` | Completion, hover, definitions, references, implementations, the file's and the project's symbols, and the error marks | | `node` | The **Run** and **Test** items of the JavaScript menu | | `npm` | The **Install** and **Start** items | | `npx` | The **Format** and **Lint** items | ## See also - [How to enable completion](enable-completion.md) — what to do when the server is installed and still says nothing - [How to run Node commands from the editor](run-node-commands.md) — the JavaScript menu - [Colouring and completion](../explanation/colouring-and-completion.md) — why the server is TypeScript's