Tooling: Node, pnpm, and the monorepo

This monorepo is a pnpm workspace. Install and Corepack always start from the repository root (ftn-site/), not from a nested app folder.

Pins (source of truth)

Pin Where

Node.js 24.x

Root package.jsonengines.node, and site-nextjs/package.jsonengines.node. Match this before installing native addons (better-sqlite3).

pnpm 11.17.0

Root package.jsonpackageManager only. Nested packages intentionally omit packageManager so Corepack / pnpm cannot disagree with the root.

Build-script allowlist

Root pnpm-workspace.yamlallowBuilds (pnpm 11). Not package.json#pnpm — that field is ignored in v11.

Install policy

Root pnpm-workspace.yamlminimumReleaseAge: 0 (avoids ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION).

Workspace members (why “4 projects”)

pnpm-workspace.yaml lists three packages. pnpm also treats the root as a workspace project. That is four members:

  1. ftn-site (root) — shared tooling (dprint, Biome), deploy helper scripts, workspace config.

  2. site-nextjs — official Next.js app (the one you develop and deploy).

  3. shared — shared design tokens / utilities.

  4. site-solidstart — retired archive; still a workspace package so the lockfile stays coherent. Do not add product features.

Product work happens in site-nextjs. The other members exist for shared code and history.

First-time machine setup

  1. Install Node.js 24 (nodejs.org LTS/Current that reports v24.x, or a version manager pointed at 24).

  2. Enable Corepack (ships with Node) and activate the repo’s pnpm pin from the repo root:

    cd Z:\code\github.com\FoodTruckNerdz\ftn-site   # or your clone path
    corepack enable
    corepack prepare pnpm@11.17.0 --activate
    pnpm --version

    You should see 11.17.0. Do not run corepack use pnpm@… only inside site-nextjs/ — that rewrites a nested pin and fights the root.

  3. Install dependencies at the root:

    pnpm install

    If pnpm asks about dependency build scripts, approve them (pnpm approve-builds). Approvals are written into pnpm-workspace.yaml under allowBuilds.

Day-to-day Next.js loop

Use two terminals, both under site-nextjs after the root install:

cd site-nextjs
copy .env.example .env.local   # first time; then fill secrets
pnpm exec convex dev           # terminal A — keep running
pnpm dev                       # terminal B — http://localhost:3000

Common scripts (from site-nextjs/):

  • pnpm dev — Next.js + Turbopack

  • pnpm build / pnpm start — production build / serve

  • pnpm lint — Next lint

  • pnpm format / pnpm format:fix — dprint check / write

  • pnpm format:biome — Biome format write

Version-fight checklist

  • Wrong Node major → native modules (better-sqlite3) ABI crash. Fix Node to 24, reinstall (pnpm install at root).

  • packageManager mismatch → Corepack error about 10.x vs 11.x. Only the root field should define pnpm; activate with corepack prepare pnpm@11.17.0 --activate.

  • pnpm field in package.json ignored → settings belong in pnpm-workspace.yaml (allowBuilds, minimumReleaseAge, etc.).

  • Install from the wrong directory → always pnpm install at the repo root so the workspace lockfile and all four members stay in sync.

  • ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION → a dependency in the lockfile is newer than minimumReleaseAge. This repo sets minimumReleaseAge: 0 in pnpm-workspace.yaml; if you raise it, wait or exclude packages with minimumReleaseAgeExclude.

  • Aborted removal of modules directory (no TTY) → major pnpm upgrades may need to recreate node_modules. Re-run with $env:CI='true' (PowerShell) or set confirmModulesPurge: false in pnpm-workspace.yaml for automation.

Changing the pnpm version (maintainers)

From the repository root:

corepack use pnpm@11.17.0

That updates root packageManager (with integrity hash). Commit package.json and any lockfile churn together. Do not leave nested packages on a different pin.