# OctoLauncher Build Guide (Windows)

End-to-end setup that gets `npm run dev` and `npm run dist` working on a fresh Windows machine. Captured from a working build on Windows 10 / April 2026.

## Changes made to the dev environment

The project as checked out does **not** build on a default up-to-date Windows dev machine. These are the deltas applied to get it working, in order:

1. **Added a Node version manager (`fnm`) and installed Node 20** alongside the existing Node 24. Node 24 was the system default and caused `nan` / `dll-inject` compile failures. Node 20 is now the fnm default but Node 24 is still available via `fnm use system`.
2. **Installed Visual Studio 2022 Build Tools** with the `VCTools` workload and Windows 11 SDK. Machine already had VS2026 (v18), but `node-gyp` v10 (shipped with Node 20's npm) doesn't detect it. VS2022 now lives side-by-side under `C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools`.
3. **Unset `ELECTRON_RUN_AS_NODE`** per-shell before launching Electron. This var is set globally by VSCode's integrated terminal (inherited from the extension host) — it is not something we can remove permanently without breaking VSCode. It has to be unset in each shell that runs `npm run dev` / `dist`.
4. **Populated `node_modules`** in both `main/` and `main/server/`. The tree was checked in empty.

Nothing in the repo itself was modified — all fixes were environmental. If another developer checks this repo out, they need to apply items 1–4 on their own machine. The sections below are that recipe.

---

## Prerequisites

### 1. Node.js 20 (not 22, not 24)

Node 24 breaks the `dll-inject` native module — its `nan` C++ bindings don't compile against V8 in Node 22+. Stick to Node 20 LTS.

Install via `fnm` so you can keep your system Node separate:

```bash
winget install Schniz.fnm --accept-source-agreements --accept-package-agreements
fnm install 20
fnm default 20
```

Verify: `node -v` should print `v20.x.x`.

### 2. Visual Studio 2022 Build Tools (C++ workload)

`dll-inject` and `stormlib-node` compile native addons via `node-gyp`. `node-gyp` v10 (bundled with Node 20's npm) only recognizes VS2017–2022 — newer VS versions (2026 / v18) are not detected.

```bash
winget install Microsoft.VisualStudio.2022.BuildTools \
  --accept-source-agreements --accept-package-agreements \
  --override "--wait --passive --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.Windows11SDK.22621 --includeRecommended"
```

~6 GB download, requires admin. Even if you already have VS2026, you need VS2022 side-by-side for node-gyp.

### 3. Python 3 (usually already present)

`node-gyp` needs Python on PATH. Any 3.x works.

## Install dependencies

From the repo root:

```bash
npm install --ignore-scripts
node node_modules/electron/install.js
node_modules/.bin/electron-builder.cmd install-app-deps
```

Why the three-step approach: `dll-inject` requires ClangCL if compiled against the system Node, but compiles fine against Electron's bundled V8 headers (which `electron-builder install-app-deps` uses). Running plain `npm install` fails if your VS2022 installation doesn't include the LLVM/ClangCL component; `--ignore-scripts` skips that step and lets `install-app-deps` handle it correctly.

Or, use the provided build script which downloads a portable Node 20 and handles everything automatically:

```powershell
.\Tools\launcher\install.ps1
```

Then the server (only needed if running a local CDN, see `server/.env.example`):

```bash
cd server
npm install
cd ..
```

## Critical env var: `ELECTRON_RUN_AS_NODE`

**VSCode's integrated terminal sets `ELECTRON_RUN_AS_NODE=1`** (inherited from VSCode's extension host). This makes Electron binaries launch as plain Node, so `require('electron')` returns a path string instead of the API — the app crashes with `TypeError: Cannot read properties of undefined (reading 'isPackaged')`.

Before any `npm run dev` / `npm run build` / `npm run dist`:

```bash
unset ELECTRON_RUN_AS_NODE 
```

```powershell
Remove-Item Env:ELECTRON_RUN_AS_NODE
```

An external terminal (Windows Terminal, cmd, plain PowerShell) doesn't have this problem — the variable is only set inside VSCode.

## Running in dev

```bash
npm run dev
```

Starts electron-vite, builds main + preload + renderer, opens an Electron window on `http://localhost:5173` (or `5174` if 5173 is taken). Closing the window ends the session.

You'll see benign warnings in the console:

- `ERROR:cache_util_win.cc ... Access is denied` — OneDrive sync locking Electron's user-data cache. Cosmetic. To silence, move the project out of OneDrive or set a custom user-data dir.
- `Browserslist: caniuse-lite is outdated` — cosmetic.

## Building for distribution

The `dist` script runs `tsc && npm run build && npm run pack`:

```bash
unset ELECTRON_RUN_AS_NODE
npm run dist
```

Outputs land in `dist/`:

- `OctoLauncher.exe` — portable single-file build
- `OctoLauncher_Installer.exe` — NSIS installer

Targets are configured in [electron-builder.yml](electron-builder.yml).

### Before publishing

- The build uses `.env.production` (committed) which already points to `https://octowow.st` — no `.env` file needed for production builds.
- Code signing is not configured. Unsigned Windows builds trigger SmartScreen warnings. To sign, add a `win.certificateFile` + password (or use env-based signing) to the electron-builder config.

## Troubleshooting

| Symptom | Cause | Fix |
|---|---|---|
| `nan_scriptorigin.h ... cannot convert 'v8::Isolate *'` during `npm install` | Node 22+ breaks `nan` | Switch to Node 20 |
| `gyp ERR! find VS Could not find any Visual Studio installation` | Only VS2023+ installed | Install VS2022 Build Tools |
| `error MSB8020: The build tools for ClangCL cannot be found` | Missing LLVM component during plain `npm install` | Use `npm install --ignore-scripts` + `electron-builder install-app-deps` (see above) |
| `TypeError: Cannot read properties of undefined (reading 'isPackaged')` at launch | `ELECTRON_RUN_AS_NODE=1` set by VSCode | `unset ELECTRON_RUN_AS_NODE` |
| `Port 5173 is in use` | Prior dev server didn't exit cleanly | Ignore (vite falls back to 5174) or kill the stale process |
