Update Node to 26 and dependencies to their latest versions

- Node 20 is end-of-life; use the current LTS in the Docker image
- Major updates: @sanity/client 8, @sanity/image-url 2,
  @portabletext/react 8, eslint-config-next 16
- Unpin React and update to 19.3
- ESLint stays on 9 and TypeScript on 6.0, since eslint-config-next's
  plugins and typescript-eslint don't support newer majors yet
- Use the native flat config from eslint-config-next 16
- Use useSyncExternalStore for WebGL detection to satisfy the new
  react-hooks lint rule

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
leanderandClaude Opus 5.5 committed 2026-10-30 22:01:56 +01:00
1 parent a1729494b4
commit aca584791e
6 files changed
+1049 -533

No files matched your search

+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:20-alpine
FROM node:26-alpine
WORKDIR /app
+6 -17
View File
@@ -1,19 +1,8 @@
import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";
import { defineConfig } from "eslint/config"
import nextVitals from "eslint-config-next/core-web-vitals"
import nextTs from "eslint-config-next/typescript"
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// eslint-config-next already ignores .next, out, build and next-env.d.ts
const eslintConfig = defineConfig([...nextVitals, ...nextTs])
const compat = new FlatCompat({
baseDirectory: __dirname,
});
const eslintConfig = [
{
ignores: [".next/**", "node_modules/**", "next-env.d.ts"],
},
...compat.extends("next/core-web-vitals", "next/typescript"),
];
export default eslintConfig;
export default eslintConfig
+1001 -487
View File
File diff suppressed because it is too large. Load diff
+16 -17
View File
@@ -12,28 +12,27 @@
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\""
},
"dependencies": {
"@portabletext/react": "^3.2.1",
"@sanity/client": "^7.8.1",
"@sanity/image-url": "^1.1.0",
"@portabletext/react": "^8.0.1",
"@sanity/client": "^8.14.1",
"@sanity/image-url": "^2.1.1",
"@sanity/webhook": "^4.0.4",
"country-flag-icons": "^1.5.19",
"country-flag-icons": "^1.6.20",
"install": "^0.13.0",
"next": "^16.3.3",
"next-intl": "^4.3.4",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-icons": "^5.5.0",
"next": "^16.4.3",
"next-intl": "^4.14.9",
"react": "^19.3.1",
"react-dom": "^19.3.1",
"react-icons": "^5.7.0",
"react-photo-sphere-viewer": "^6.2.3"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "15.4.4",
"prettier": "^3.6.2",
"typescript": "^5"
"@types/node": "^26.6.6",
"@types/react": "^19.3.0",
"@types/react-dom": "^19.3.0",
"eslint": "^9.39.5",
"eslint-config-next": "^16.4.3",
"prettier": "^3.9.10",
"typescript": "~6.0.3"
},
"repository": {
"type": "git",
+20 -8
View File
@@ -1,21 +1,33 @@
"use client"
import { useEffect, useState } from "react"
import { useSyncExternalStore } from "react"
import { useTranslations } from "next-intl"
import Image from "next/image"
import { ReactPhotoSphereViewer } from "react-photo-sphere-viewer"
import * as styles from "./office.module.css"
let webGL2Support: boolean | undefined
// Checked once, since creating a WebGL context is not free
const getWebGL2Support = () => {
webGL2Support ??= Boolean(
document.createElement("canvas").getContext("webgl2")
)
return webGL2Support
}
// WebGL support never changes, so there is nothing to subscribe to
const subscribe = () => () => {}
const Office = () => {
const t = useTranslations("office")
const [supportsWebGL2, setSupportsWebGL2] = useState<boolean | null>(null)
useEffect(() => {
const canvas = document.createElement("canvas")
const gl = canvas.getContext("webgl2")
setSupportsWebGL2(Boolean(gl))
}, [])
// null on the server, which renders the fallback image
const supportsWebGL2 = useSyncExternalStore(
subscribe,
getWebGL2Support,
() => null
)
return (
<section id="office">
+5 -3
View File
@@ -1,9 +1,11 @@
import imageUrlBuilder from "@sanity/image-url"
import type { SanityImageSource } from "@sanity/image-url/lib/types/types"
import {
createImageUrlBuilder,
type SanityImageSource,
} from "@sanity/image-url"
import { sanityClient } from "./sanity"
const builder = imageUrlBuilder(sanityClient)
const builder = createImageUrlBuilder(sanityClient)
export function urlFor(source: SanityImageSource) {
return builder.image(source)