feat: migration Next.js 15 → 16 (Turbopack, ESLint 9, proxy)

- Next.js 15.5.12 → 16.1.6 avec Turbopack par défaut
- ESLint 8 → 9 + migration flat config (eslint.config.mjs)
- eslint-config-next 15 → 16, eslint-config-prettier 9 → 10
- @types/node 18 → 22 (aligné avec nodejs_22 du flake.nix)
- middleware.ts → proxy.ts (nouvelle convention Next.js 16)
- global-error.tsx : import dynamique de Sentry (fix prerendering Turbopack)
- CSS : @import Google Fonts déplacé en tête de fichier (requis par Turbopack)
- .prettierignore : ajout next-env.d.ts et .clever.json (fichiers auto-générés)
This commit is contained in:
Jalil Arfaoui 2026-02-21 16:30:21 +01:00
parent 9aa8fd80e5
commit 594992c233
12 changed files with 657 additions and 605 deletions

View file

@ -1 +0,0 @@
node_modules

View file

@ -1,3 +0,0 @@
{
"extends": ["next/core-web-vitals", "prettier"]
}

View file

@ -7,3 +7,5 @@ debats-elixir
frontend frontend
ruby-backend ruby-backend
api api
.clever.json
next-env.d.ts

View file

@ -1,6 +1,5 @@
'use client' 'use client'
import * as Sentry from '@sentry/nextjs'
import { useEffect } from 'react' import { useEffect } from 'react'
export default function GlobalError({ export default function GlobalError({
@ -11,7 +10,9 @@ export default function GlobalError({
reset: () => void reset: () => void
}) { }) {
useEffect(() => { useEffect(() => {
Sentry.captureException(error) import('@sentry/nextjs').then((Sentry) => {
Sentry.captureException(error)
})
}, [error]) }, [error])
return ( return (

31
eslint.config.mjs Normal file
View file

@ -0,0 +1,31 @@
import { defineConfig, globalIgnores } from 'eslint/config'
import nextVitals from 'eslint-config-next/core-web-vitals'
import prettier from 'eslint-config-prettier/flat'
const eslintConfig = defineConfig([
...nextVitals,
prettier,
{
// TODO: fix these react-hooks issues then remove these overrides
rules: {
'react-hooks/error-boundaries': 'warn',
'react-hooks/set-state-in-effect': 'warn',
'react-hooks/refs': 'warn',
},
},
globalIgnores([
'.next/**',
'out/**',
'build/**',
'next-env.d.ts',
'frontend/**',
'api/**',
'ruby-backend/**',
'debats-elixir/**',
'content/**',
'docs/**',
'scripts/**',
]),
])
export default eslintConfig

1
index.d.ts vendored
View file

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
declare module '*.svg' { declare module '*.svg' {
const content: any const content: any
export const ReactComponent: any export const ReactComponent: any

1
next-env.d.ts vendored
View file

@ -1,5 +1,6 @@
/// <reference types="next" /> /// <reference types="next" />
/// <reference types="next/image-types/global" /> /// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts";
// NOTE: This file should not be edited // NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

1190
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint", "lint": "eslint .",
"format": "prettier --write .", "format": "prettier --write .",
"format:check": "prettier --check .", "format:check": "prettier --check .",
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
@ -26,19 +26,19 @@
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"downshift": "^9.3.0", "downshift": "^9.3.0",
"effect": "^3.16.12", "effect": "^3.16.12",
"next": "^15.5.12", "next": "^16.0.0",
"next-plausible": "^3.12.5", "next-plausible": "^3.12.5",
"react": "^19.2.4", "react": "^19.2.4",
"react-dom": "^19.2.4" "react-dom": "^19.2.4"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "18.16.9", "@types/node": "^22.0.0",
"@types/react": "^19.2.14", "@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"@vitest/ui": "^3.2.4", "@vitest/ui": "^3.2.4",
"eslint": "~8.48.0", "eslint": "^9.0.0",
"eslint-config-next": "^15.5.12", "eslint-config-next": "^16.0.0",
"eslint-config-prettier": "^9.0.0", "eslint-config-prettier": "^10.1.8",
"prettier": "^3.8.1", "prettier": "^3.8.1",
"supabase": "^2.76.8", "supabase": "^2.76.8",
"tsx": "^4.21.0", "tsx": "^4.21.0",

View file

@ -1,7 +1,7 @@
import { type NextRequest } from 'next/server' import { type NextRequest } from 'next/server'
import { updateSession } from './infra/supabase/middleware' import { updateSession } from './infra/supabase/middleware'
export async function middleware(request: NextRequest) { export async function proxy(request: NextRequest) {
return await updateSession(request) return await updateSession(request)
} }

View file

@ -1,3 +1,5 @@
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic');
:root { :root {
--debats-red: #f21e40; --debats-red: #f21e40;
@ -27,8 +29,6 @@
font-style: normal; font-style: normal;
} }
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic');
html { html {
height: 100%; height: 100%;
} }

View file

@ -11,7 +11,7 @@
"moduleResolution": "node", "moduleResolution": "node",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"jsx": "preserve", "jsx": "react-jsx",
"incremental": true, "incremental": true,
"plugins": [ "plugins": [
{ {
@ -24,6 +24,12 @@
}, },
"forceConsistentCasingInFileNames": true "forceConsistentCasingInFileNames": true
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts"
],
"exclude": ["node_modules"] "exclude": ["node_modules"]
} }