Skip to content

chore: upgrade to node 24 lts and pnpm 10#53

Merged
bolin8017 merged 1 commit into
mainfrom
chore/upgrade-node24-pnpm10
Apr 18, 2026
Merged

chore: upgrade to node 24 lts and pnpm 10#53
bolin8017 merged 1 commit into
mainfrom
chore/upgrade-node24-pnpm10

Conversation

@bolin8017
Copy link
Copy Markdown
Owner

Summary

  • Vercel has defaulted to Node 24 since 2026-03, while CI + .nvmrc stayed on Node 22 — aligning local/CI with production removes a source of environment drift.
  • Node 22 entered maintenance in October 2025 (security fixes only); Node 24 is active LTS through April 2028.
  • pnpm 10.33.0 pairs better with Node 24 (auto-install-peers default on, stricter peer-dep resolution, faster lockfile regen). Doing both in one PR avoids a second lockfile regeneration a week later.

Changes:

  • .nvmrc: 22 → 24
  • .github/workflows/ci.yml: node-version: 2224
  • package.json: packageManager pnpm@9.15.0 → pnpm@10.33.0; engines.node >=20.0.0>=22.0.0 (contributors still on 22 can develop, CI + prod use 24); engines.pnpm >=9.15.0>=10.0.0
  • pnpm-lock.yaml: regenerated with pnpm 10.33.0 (+58/-42 lines, lockfile format still v9)

Test plan

  • pnpm build (web + shared): green
  • pnpm --filter @caffecode/shared test: 186 passed
  • pnpm --filter @caffecode/web test: 571 passed
  • tsc --noEmit for shared + web: green
  • pnpm --filter @caffecode/web lint: green
  • pnpm 10 stricter peer-dep resolution surfaced no conflicts

Follow-up

  • Contributors need to run corepack enable && corepack prepare pnpm@10.33.0 --activate or nvm use after pulling; lockfile regeneration is already in the PR so pnpm install will just reuse entries.

Stay on current LTS. Vercel's build environment has defaulted to Node
24 since 2026-03; keeping local dev and CI on Node 22 let drift
accumulate between the platforms that ship the app and the environment
we develop in. Node 22 entered maintenance in October 2025 and will
only see security fixes; Node 24 is active LTS through April 2028.

Bumping pnpm at the same time because pnpm 10 is now stable enough to
be the default on most CI platforms and pairs better with Node 24
(auto-install-peers is on by default, stricter peer-dep resolution,
faster lockfile regeneration). Doing both in one PR avoids two
separate lockfile regenerations a week apart.

Changes:
- .nvmrc: 22 -> 24 (picks up Node 24 on nvm use)
- .github/workflows/ci.yml: node-version 22 -> 24
- package.json: packageManager pnpm@9.15.0 -> pnpm@10.33.0; engines
  node >=20.0.0 -> >=22.0.0 (allow Node 22 for contributors still on
  it, while CI + prod use 24); engines pnpm >=9.15.0 -> >=10.0.0
- pnpm-lock.yaml: regenerated with pnpm 10.33.0

Verified locally: pnpm build (web + shared), pnpm test (186 shared +
571 web = 757 passing), tsc --noEmit, eslint — all green. pnpm 10's
stricter peer-dep resolution surfaced no conflicts on this workspace.
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 18, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
caffecode Ready Ready Preview, Comment Apr 18, 2026 9:36am

@github-actions
Copy link
Copy Markdown

📊 Coverage Report

Package Statements Branches Functions Lines
shared 92.22% ❌ (≥95%) 87.74% ❌ (≥90%) 96.87% ✅ (≥95%) 91.88% ❌ (≥95%)
web 94.03% ✅ (≥90%) 89.26% ✅ (≥85%) 96.5% ✅ (≥90%) 94.77% ✅ (≥90%)

🤖 Generated by CI · thresholds enforced via vitest

@bolin8017 bolin8017 merged commit 6488ff9 into main Apr 18, 2026
3 checks passed
@bolin8017 bolin8017 deleted the chore/upgrade-node24-pnpm10 branch April 18, 2026 10:06
bolin8017 added a commit that referenced this pull request Apr 18, 2026
## Summary

- Enables `cacheComponents: true` and migrates the whole app to Next.js
16 Partial Prerendering: static shells + cached data + dynamic Suspense
regions in every route.
- Public pages now serve a cached static shell with per-user dynamic
regions (solved checkmarks, progress bars) streaming in — SEO-critical
problem and list content is rendered instantly.
- Admin mutations (`deleteProblem`, `flagForRegeneration`,
`unflagRegeneration`) call `revalidateTag(..., 'max')` for tag-scoped
cache invalidation, replacing the hourly ISR window — admin edits
propagate in seconds.
- The earlier reverted attempt (documented in
`docs/deferred-improvements.md`) failed because `cacheComponents: true`
requires every runtime data access (cookies, headers, awaited
params/searchParams, Supabase auth) to sit inside a `<Suspense>`
boundary; that's what this PR methodically fixes across ~20 files.

## What changed structurally

- **Config**: `cacheComponents: true` in `apps/web/next.config.ts`.
- **Layouts**: root (`app/layout.tsx`), admin, and `(auth)` now have a
synchronous static chrome shell. Auth/header reads live in a
Suspense-wrapped async child. Redirect semantics unchanged — proxy.ts
still does the primary gate.
- **Pages**: every page that awaits params/searchParams or reads cookies
has a sync default export that wraps an async `PageBody` child in
`<Suspense>`. Covers all 4 public pages, 7 admin pages, 6 auth pages,
landing, login.
- **Public pages**: shared data fetches converted from `react.cache` to
`'use cache'` + `cacheLife('hours')` + `cacheTag(...)`. Cached helpers:
`getProblemBySlug`, `getListBySlug`, `getListProblems`,
`getFilteredProblems`, `getFilteredLists`, `getSitemapData`.
- **Cache tag vocabulary**: `problems`, `problem:<slug>`, `lists`,
`list:<slug>`, `list:<id>:problems`.
- **Admin mutations**: `_admin-helpers.ts` gains a `tags: string[]`
option; affected actions pass the right tags.
- **API routes**: `dynamic = 'force-dynamic'` removed from
`api/cron/push` and `api/health` (incompatible with cacheComponents;
handlers default to dynamic anyway).
- **Request-scoped time**: admin pages using `new Date()`/`Date.now()`
for query construction now `await connection()` first.

## Test plan

- `pnpm build`: all 32 routes compile. 18 are Partial Prerender (◐), the
rest static (○) or API-dynamic (ƒ).
- `pnpm --filter @caffecode/shared test`: 186 passed.
- `pnpm --filter @caffecode/web test`: 571 passed. Added `revalidateTag`
to the `next/cache` mock; exposed `LoginPageBody` as a named export for
direct test invocation.
- `tsc --noEmit` for shared + web: clean.
- `pnpm --filter @caffecode/web lint`: clean.

## Follow-up

- After merge, monitor `/admin/content` edits → confirm public
`/problems/[slug]` reflects changes within seconds (no longer bounded by
the 1h ISR).
- The three deferred-improvements items from the 2026-04-17 review are
now resolved: Cache Components done (this PR), Node 24 + pnpm 10 done
(PR #53), Branded channel-identifier types decided skipped (doc
updated).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant