build(web): pin the toolchain and bump every dependency to latest

The repo could not be built at all. Two independent faults, both from an
unpinned toolchain:

1. `corepack enable pnpm` with no `packageManager` field fetched whatever pnpm
   was newest at build time. pnpm 11 REMOVED `onlyBuiltDependencies` (replaced
   by `allowBuilds`) and made `strictDepBuilds` default to true, so the sharp
   allowlist that package.json still carried was silently ignored and install
   died with ERR_PNPM_IGNORED_BUILDS. pnpm 11 also demotes `.npmrc` to
   auth/registry only, so settings must live in pnpm-workspace.yaml.

   Fixed by pinning `packageManager: [email protected].0` and moving the setting to
   pnpm-workspace.yaml in its current form (`allowBuilds: {sharp: true}`).

2. The `pnpm` field in package.json is dead weight under pnpm 11 — removed
   rather than left to rot as a second, ignored source of the same setting.

Dependencies taken to latest, including four majors:

  typescript      5.9.3   (NOT 7.0.2 — see below)
  zod             3 -> 4
  recharts        2 -> 3
  lucide-react    0.544 -> 1.26
  next            16.0.1 -> 16.2.11
  react/-dom      19.2.0 -> 19.2.8
  @hanzo/iam      0.11 -> 0.13.8
  tailwindcss     4.1 -> 4.3.3
  @types/node     22 -> 24 (aligned to the runtime, not bumped past it)
  + every Radix, TanStack and support package

TypeScript is deliberately held at 5.9.3, the newest that works. 7.0.2 is the
Go-native rewrite with a different package shape; Next 16.2 cannot resolve it
and the build fails after compiling, in Next's TypeScript step, with
`The "id" argument must be of type string. Received undefined` after it tries
to reinstall typescript itself. Revisit when Next declares support.

Base image node:22-alpine -> node:24-alpine (Active LTS; 26 is Current, not
LTS), digest-pinned so it cannot drift the way pnpm did. pnpm 11 needs Node
>= 22 regardless.

Verified locally, not assumed: `pnpm install` exits 0, `tsc --noEmit` reports
0 errors across the whole bumped tree, and `pnpm run build` exits 0 with every
route prerendered.
This commit is contained in:
2026-07-26 10:32:54 -07:00
parent b53533db53
commit 4b9de98537
4 changed files with 1194 additions and 1215 deletions
+10 -2
View File
@@ -2,7 +2,10 @@
# Next.js 15 with React 19
# Pinned digest for supply chain security - update periodically
FROM node:22-alpine@sha256:e4bf2a82ad0a4037d28035ae71529873c069b13eb0455466ae0bc13363826e34 AS base
# Node 24 = Active LTS. Node 26 is Current, not LTS, so it is not the base for a
# production image. Digest-pinned so the base cannot move under us the way the
# unpinned pnpm did. pnpm 11 also requires Node >= 22.
FROM node:24-alpine@sha256:a0b9bf06e4e6193cf7a0f58816cc935ff8c2a908f81e6f1a95432d679c54fbfd AS base
# Install dependencies only when needed
FROM base AS deps
@@ -10,7 +13,12 @@ RUN apk add --no-cache libc6-compat
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json pnpm-lock.yaml* ./
# pnpm-workspace.yaml carries the pnpm settings (onlyBuiltDependencies) that
# pnpm >= 11 no longer reads from package.json. It must land before install or
# sharp's build script is skipped and the install fails ERR_PNPM_IGNORED_BUILDS.
# package.json's `packageManager` field pins which pnpm corepack fetches, so the
# build no longer changes behaviour whenever a new pnpm is published.
COPY package.json pnpm-lock.yaml* pnpm-workspace.yaml ./
RUN corepack enable pnpm && pnpm install --frozen-lockfile
# Rebuild the source code only when needed
+41 -43
View File
@@ -1,6 +1,7 @@
{
"name": "@bootnode/web",
"version": "2.0.0",
"packageManager": "[email protected]",
"private": true,
"type": "module",
"scripts": {
@@ -11,58 +12,55 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@hanzo/iam": "^0.11.0",
"@luxfi/logo": "^1.0.0",
"@radix-ui/react-accordion": "^1.2.2",
"@radix-ui/react-alert-dialog": "^1.1.4",
"@radix-ui/react-avatar": "^1.1.11",
"@radix-ui/react-checkbox": "^1.1.3",
"@radix-ui/react-collapsible": "^1.1.2",
"@radix-ui/react-dialog": "^1.1.4",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.1",
"@radix-ui/react-navigation-menu": "^1.2.3",
"@radix-ui/react-popover": "^1.1.4",
"@radix-ui/react-progress": "^1.1.1",
"@radix-ui/react-scroll-area": "^1.2.2",
"@radix-ui/react-select": "^2.1.4",
"@radix-ui/react-separator": "^1.1.1",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-switch": "^1.1.2",
"@radix-ui/react-tabs": "^1.1.2",
"@radix-ui/react-toast": "^1.2.4",
"@radix-ui/react-tooltip": "^1.1.6",
"@tanstack/react-query": "^5.62.0",
"@tanstack/react-table": "^8.20.6",
"@hanzo/iam": "^0.13.8",
"@luxfi/logo": "^1.0.7",
"@radix-ui/react-accordion": "^1.2.20",
"@radix-ui/react-alert-dialog": "^1.1.23",
"@radix-ui/react-avatar": "^1.2.6",
"@radix-ui/react-checkbox": "^1.3.11",
"@radix-ui/react-collapsible": "^1.1.20",
"@radix-ui/react-dialog": "^1.1.23",
"@radix-ui/react-dropdown-menu": "^2.1.24",
"@radix-ui/react-label": "^2.1.15",
"@radix-ui/react-navigation-menu": "^1.2.22",
"@radix-ui/react-popover": "^1.1.23",
"@radix-ui/react-progress": "^1.1.16",
"@radix-ui/react-scroll-area": "^1.2.18",
"@radix-ui/react-select": "^2.3.7",
"@radix-ui/react-separator": "^1.1.15",
"@radix-ui/react-slot": "^1.3.3",
"@radix-ui/react-switch": "^1.3.7",
"@radix-ui/react-tabs": "^1.1.21",
"@radix-ui/react-toast": "^1.2.23",
"@radix-ui/react-tooltip": "^1.2.16",
"@tanstack/react-query": "^5.101.4",
"@tanstack/react-table": "^8.21.3",
"@types/d3": "^7.4.3",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"d3": "^7.9.0",
"date-fns": "^4.1.0",
"geist": "^1.5.1",
"lucide-react": "^0.544.0",
"next": "^16.0.1",
"next-themes": "^0.4.4",
"nuqs": "^2.2.3",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"recharts": "^2.15.4",
"date-fns": "^4.4.0",
"geist": "^1.7.2",
"lucide-react": "^1.26.0",
"next": "^16.2.11",
"next-themes": "^0.4.6",
"nuqs": "^2.9.2",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"recharts": "^3.10.1",
"sonner": "^2.0.7",
"tailwind-merge": "^3.3.1",
"tailwind-merge": "^3.6.0",
"tailwindcss-animate": "^1.0.7",
"zod": "^3.24.1"
"zod": "^4.4.3"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.1.17",
"@types/node": "^22.19.7",
"@types/react": "^19.2.0",
"@types/react-dom": "^19.2.0",
"postcss": "^8.5.3",
"tailwindcss": "^4.1.17",
"@tailwindcss/postcss": "^4.3.3",
"@types/node": "^24.13.3",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"postcss": "^8.5.23",
"tailwindcss": "^4.3.3",
"typescript": "^5.9.3"
},
"pnpm": {
"onlyBuiltDependencies": ["sharp"]
}
}
+1128 -1170
View File
File diff suppressed because it is too large Load Diff
+15
View File
@@ -0,0 +1,15 @@
# pnpm settings. As of pnpm 11 the `pnpm` field in package.json is no longer
# read and `.npmrc` is auth/registry only — every other setting lives here.
# `packageManager` in package.json pins the version corepack resolves, so this
# file and the running pnpm can never disagree.
#
# Without that pin, `corepack enable pnpm` fetched whatever pnpm was newest at
# build time. When pnpm 11 shipped it removed `onlyBuiltDependencies` outright
# (replaced by `allowBuilds`) and made `strictDepBuilds` default to true, so the
# old allowlist silently stopped applying and every build of this repo began
# failing with ERR_PNPM_IGNORED_BUILDS.
#
# sharp compiles a native binary that Next.js uses for image optimisation, so it
# must be allowed to run its install script.
allowBuilds:
sharp: true