Skip to content

MAINT: Update npm dependencies - #92

Merged
VeckoTheGecko merged 20 commits into
mainfrom
update-npm-deps
Oct 28, 2026
Merged

VeckoTheGecko merged 20 commits into
mainfrom
update-npm-deps

Conversation

@VeckoTheGecko

@VeckoTheGecko VeckoTheGecko commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

I have gone through all the code here, and think that it looks good. I have also done inspections of the website.


Note

This PR (code changes and this description) was generated by an LLM (Claude Opus 5.5). Please review with that in mind, especially the Chakra UI v3 migration.

Updates every npm dependency to its latest version, except two that are held back (see below), and migrates the code to match. Each upgrade is its own commit, so the PR is easiest to review commit by commit.

Version bumps

Major

Package From To
next, @next/mdx 14 16.4.3
eslint-config-next 15.2.4 16.4.3
react, react-dom 18.3 19.3.1
@types/react 18.3 19.3.0
@chakra-ui/react 2.9 3.37.0
eslint 9 10.13.0
typescript >=5.7.3 ^6.0.3
date-fns 3 4.4.0
feed 4.2 6.0.0
glob 11 13.0.6
framer-motion 11 14.7.0
next-mdx-remote 5 6.0.0
react-ga4 2.1 3.0.1
react-syntax-highlighter 15 16.1.2
apexcharts / react-apexcharts 4 / 1.4 8.5.0 / 2.1.1
isomorphic-dompurify 2.16 ~3.19.0
three 0.185 0.186.1

Minor/patch

@emotion/react, @fontsource-variable/inter, @mdx-js/loader, @mdx-js/react, react-icons, swr, playwright, webpack.

Removed

@chakra-ui/icons, @chakra-ui/next-js, @chakra-ui/system, @emotion/styled. Chakra v3 no longer uses them, or they were unused.

Code and config changes

Next.js 16

  • next.config.mjs: images.domains → images.remotePatterns. rehype-slug is now referenced by package name, because Turbopack (now the default bundler) requires serializable loader options.
  • next lint was removed, so the lint script is now eslint ., and .eslintrc is replaced by a flat eslint.config.mjs.
  • Next regenerated tsconfig.json (jsx: react-jsx) and next-env.d.ts. *.tsbuildinfo is now gitignored.

Chakra UI v3 (migrated by hand)

  • src/theme.js uses createSystem, and ChakraProvider takes value={system}. The theme re-declares the v2 container sizes and padding, heading scale and body text colour, so the site looks the same.
  • Components moved to their v3 forms: Accordion, Alert, Avatar, Card, Collapsible, Modal → Dialog, Divider → Separator. The desktop-nav hover popover is now a HoverCard.
  • New local Tooltip snippet: src/components/ui/tooltip.js.
  • Prop renames: spacing → gap, noOfLines → lineClamp, colorScheme → colorPalette, isExternal → target/rel, plus the useDisclosure and useClipboard API changes.
  • @chakra-ui/icons is replaced by react-icons (Lucide set). The link wrapper uses asChild with next/link.
  • Before/after screenshots of every page, on desktop and mobile, are near-identical. Some default palette shades (e.g. link blue) differ slightly.

feed v6

  • Atom entry ids must now be URIs. The bare post slugs made the feed generator throw, so atom.xml and rss.json were silently not being generated while the build still reported success. Entries now use the post permalink as their id, and authors now appear in the RSS feed.
  • ⚠️ This changes the RSS guid and Atom id of existing posts, so feed readers may show them as new once.

TypeScript 6

  • The tsconfig.json target moves from es5 (deprecated in TS 6) to ES2017.

Lint fixes

Linting was already broken on main: next lint crashed on ESLint 9. Running it again surfaced:

  • a missing Image import in ProjectCard (that component isn't currently rendered);
  • an unescaped apostrophe on the about page;
  • stale eslint-disable comments;
  • a deliberate state reset in the Panorama effect, now suppressed with a comment explaining why.

No code changes needed

React 19, date-fns 4, glob 13, next-mdx-remote 6, react-ga4 3, react-syntax-highlighter 16, three r186, framer-motion 14.

Held back

  • isomorphic-dompurify stays at ~3.19.0, not 4.x. v4 (via jsdom) needs Node ^22.22 / ^24.15 / >=26, and the deploy workflow builds on Node 20, which reaches only 3.19. It can be bumped once CI moves to a newer Node.
  • typescript stays at 6.x, not 7. TS 7 no longer ships the classic compiler API, which typescript-eslint (via eslint-config-next) and Next's build-time type check still need.

Known caveats

  • npm prints ERESOLVE overriding peer dependency warnings for ESLint 10, because eslint-plugin-react, -import and -jsx-a11y don't declare support for it yet. npm ci succeeds and the rules still work.
  • next dev now writes an AGENTS.md into the repo root. It isn't committed here. Decide whether to gitignore it, commit it, or turn it off with agentRules: false.
  • apexcharts, react-apexcharts and d3 aren't imported anywhere and could be removed in a follow-up.

Testing

  • npm run build passes on Node 24 and Node 20.
  • npm run lint passes with 0 problems.
  • npx tsc --noEmit passes.
  • The build-cards script (Playwright screenshots) was not run end to end.
  • Checked manually in dev: accordion, dialog, tooltip and mobile menu work, and there are no React warnings.

🤖 Generated with Claude Code

Bump all dependencies within their current major versions, refresh the
lockfile, and pin typescript to ^5.9.3 (the previous >=5.7.3 range would
otherwise pull in TypeScript 7).
- next 14.2.35 -> 16.4.3, @next/mdx 14.2.35 -> 16.4.3,
  eslint-config-next 15.5.28 -> 16.4.3
- next.config.mjs: reference rehype-slug by package name so the MDX
  loader options are serializable for Turbopack (now the default
  bundler), and replace the deprecated images.domains with
  images.remotePatterns
- `next lint` was removed in Next.js 16: switch the lint script to the
  ESLint CLI and migrate .eslintrc to a flat eslint.config.mjs using
  eslint-config-next/core-web-vitals
- Fix issues surfaced now that linting runs again: missing Image import
  in ProjectCard, unescaped apostrophe on the about page, stale
  eslint-disable directives, and an intentional state reset in the
  Panorama effect (react-hooks/set-state-in-effect)
- tsconfig.json / next-env.d.ts updated by Next.js (jsx: react-jsx);
  ignore generated *.tsbuildinfo
- react 18.3.1 -> 19.3.1, react-dom 18.3.1 -> 19.3.1
- @types/react 18.3.31 -> 19.3.0

No code changes were required: the site uses the pages router and none
of the APIs removed in React 19 (propTypes/defaultProps on function
components, string refs, legacy context, ReactDOM.render).
date-fns 3.6.0 -> 4.4.0. The v4 breaking changes (first-class time zone
support, stricter types) do not affect our use of formatDistanceToNow;
date-fns-tz 3.2 already supports date-fns ^4. Rendered dates are
unchanged.
feed 4.2.2 -> 6.0.0 (now an ESM package requiring Node >= 20).

feed v6 validates that Atom entry ids are URIs and threw
'TypeError: Invalid URL' for our bare post slugs, so atom.xml and
rss.json were no longer generated. Use the post permalink as the item
id instead. Note that this changes the RSS guid / Atom id of existing
posts, so feed readers may show them once more as new items. Post
authors are now also emitted in the RSS feed.
glob 11.1.0 -> 13.0.6. The v12/v13 breaking changes (CLI moved to the
separate glob-bin package, Node >= 20) do not affect our use of
glob.sync; all blog posts are still discovered.
isomorphic-dompurify 2.36.0 -> 3.19.0 (jsdom 29), pinned with ~3.19.0.

v4 (and the deprecated 3.20-3.23 releases) pull in jsdom 30, which
requires Node ^22.22.2 || ^24.15.0 || >=26. Under Node 20, which the
deploy workflow currently uses, `next build` fails with "Failed to
load external module isomorphic-dompurify ... Cannot read properties
of undefined (reading 'bind')". 3.19.0 is the latest release that still
supports Node 20; move to v4 once CI runs on a newer Node.
next-mdx-remote 5.0.0 -> 6.0.0. v6 strips JavaScript expressions from
MDX by default (blockJS / blockDangerousJS). None of the blog posts use
JS expressions (the only component, <Panorama>, takes string props), so
the secure defaults are kept; rendered post content is unchanged.
react-ga4 2.1.0 -> 3.0.1. v3 is a rewrite in TypeScript published as
ESM only; the default ReactGA export with initialize()/send() is
unchanged, so no code changes are needed.
react-syntax-highlighter 15.6.6 -> 16.1.2. The only breaking change is
the move to refractor v5; the Prism highlighter and the nord style
import path used in the MDX Code component are unchanged and still
highlight correctly.
three 0.185.1 -> 0.186.1. None of the r186 removals/deprecations touch
the APIs used by the 360-video Panorama viewer (WebGLRenderer,
VideoTexture, SphereGeometry, MeshBasicMaterial, PerspectiveCamera,
MathUtils).
apexcharts 4.7.0 -> 8.5.0, react-apexcharts 1.9.0 -> 2.1.1 (upgraded
together since react-apexcharts 2 requires apexcharts >= 5.10). Neither
package is currently imported anywhere in the site, so no code changes
are needed.
framer-motion 11.18.2 -> 14.6.0. Breaking changes reviewed:
- v12: gesture start callbacks receive the target element first
- v13: optional @emotion/is-prop-valid dependency removed
- v14: removal of internal compatibility APIs
None affect the plain motion.div whileHover/whileTap usage on the blog
index or Chakra UI v2's animated components (Collapse, Popover), which
were checked in dev mode without warnings.
eslint 9.39.5 -> 10.13.0. The flat config (eslint.config.mjs) already
matches what ESLint 10 requires (eslintrc support was removed).

eslint-plugin-react, eslint-plugin-import and eslint-plugin-jsx-a11y
(pulled in by eslint-config-next) do not yet list ESLint 10 in their
peerDependencies, so npm prints 'ERESOLVE overriding peer dependency'
warnings on install. Installs (including npm ci) succeed and the rules
from all bundled plugins were checked to still report correctly.
typescript 5.9.3 -> 6.0.3. TypeScript 6 deprecates target ES5, so the
tsconfig target is raised to ES2017 (the Next.js default; it only
affects type checking since Next compiles the code itself).

TypeScript 7.0.2 (the native Go port) was tried but is not usable yet:
it no longer ships the classic compiler API, so eslint-config-next
(via typescript-eslint, which supports typescript >=4.8.4 <6.1.0)
crashes on load, and Next's build-time type check rejects the config.
@chakra-ui/react 2.10.10 -> 3.37.0; @emotion/react 11.14.0 (still a
peer dependency). Removed packages that are gone or unused in v3:
@chakra-ui/icons, @chakra-ui/next-js, @chakra-ui/system and
@emotion/styled. framer-motion stays as a direct dependency because the
blog index uses it directly.

Migration (following the official v2 -> v3 guide):
- theme.js: extendTheme -> createSystem(defaultConfig, defineConfig(...));
  ChakraProvider now takes `value={system}`. Fonts, smooth scrolling
  and the body text colour are carried over, and the v2 `container.*`
  sizes, container padding and Heading size scale are re-declared so
  existing `maxW='container.lg'` / `size=` props render as before.
- Compound components: Accordion, Alert, Avatar, Card, Collapse ->
  Collapsible, Modal -> Dialog, Divider/StackDivider -> Separator,
  Tooltip via a local snippet (src/components/ui/tooltip.js), desktop
  nav dropdown Popover(trigger=hover) -> HoverCard
- Props: spacing -> gap, noOfLines -> lineClamp, colorScheme ->
  colorPalette, leftIcon/icon -> children, isOpen -> open
  (useDisclosure), useClipboard({ value }), isExternal ->
  target/rel, `as={Flex}` on Container -> display='flex'
- @chakra-ui/icons replaced by react-icons (Lucide set)
- Link wrapper uses `asChild` with next/link

Verified with before/after screenshots of every page (desktop and
mobile) plus interaction checks (accordion, dialog, tooltip, mobile
menu) and no React warnings in dev mode.

@erikvansebille erikvansebille left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one looks good too!

Note that when I do an npm install, it creates the following change:

diff --git a/next-env.d.ts b/next-env.d.ts
index 1d70fd3..03d35cb 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,7 +1,7 @@
 /// <reference types="next" />
 /// <reference types="next/image-types/global" />
-import './.next/dev/types/routes.d.ts'
-import './.next/dev/types/root-params.d.ts'
+import "./.next/dev/types/routes.d.ts";
+import "./.next/dev/types/root-params.d.ts";

Should we update the code?

@VeckoTheGecko

Copy link
Copy Markdown
Collaborator Author

Ah, I thought I already pushed those changes. Done now

@VeckoTheGecko
VeckoTheGecko merged commit 3fed2f6 into main Oct 28, 2026
2 of 3 checks passed
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.

2 participants