diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..1d32836
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,15 @@
+{
+ "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
+ "parser": "@typescript-eslint/parser",
+ "parserOptions": {
+ "ecmaVersion": "latest",
+ "sourceType": "module",
+ "ecmaFeatures": { "jsx": true }
+ },
+ "plugins": ["@typescript-eslint"],
+ "rules": {
+ "@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
+ "@typescript-eslint/no-explicit-any": "warn"
+ },
+ "ignorePatterns": ["node_modules/", "out/", ".next/", "api/"]
+}
diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml
index c6e0781..65a228d 100644
--- a/.gitea/workflows/deploy.yml
+++ b/.gitea/workflows/deploy.yml
@@ -45,7 +45,7 @@ jobs:
if: steps.changes.outputs.frontend == 'true'
uses: actions/setup-node@v4
with:
- node-version: 18
+ node-version: 20
- name: Install dependencies
if: steps.changes.outputs.frontend == 'true'
diff --git a/next-env.d.ts b/next-env.d.ts
index 830fb59..9edff1c 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,6 +1,6 @@
///
///
-///
+import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/package-lock.json b/package-lock.json
index dc01ff7..a0d287d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,31 +12,31 @@
"axios": "^1.6.2",
"bcryptjs": "^3.0.2",
"cheerio": "^1.1.0",
- "next": "^15.3.4",
+ "next": "^16.1.6",
"pg": "^8.16.2",
- "react": "^19.1.0",
- "react-dom": "^19.1.0"
+ "react": "^19.2.4",
+ "react-dom": "^19.2.4"
},
"devDependencies": {
- "@testing-library/jest-dom": "^6.6.3",
- "@testing-library/react": "^16.3.0",
+ "@testing-library/jest-dom": "^6.9.1",
+ "@testing-library/react": "^16.3.2",
"@types/jest": "^30.0.0",
- "@types/react": "^18.2.43",
- "@types/react-dom": "^18.2.17",
+ "@types/react": "^19.2.14",
+ "@types/react-dom": "^19.2.3",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
"@vitejs/plugin-react": "^4.2.1",
- "autoprefixer": "^10.4.16",
+ "autoprefixer": "^10.4.24",
"eslint": "^8.55.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.5",
"husky": "^9.1.7",
"jest": "^30.0.0",
"jest-environment-jsdom": "^30.0.0",
- "postcss": "^8.4.32",
+ "postcss": "^8.5.6",
"tailwindcss": "^3.3.0",
- "tsx": "^4.20.3",
- "typescript": "^5.2.2",
+ "tsx": "^4.21.0",
+ "typescript": "^5.9.3",
"vite": "^5.0.8"
}
},
@@ -2477,15 +2477,15 @@
}
},
"node_modules/@next/env": {
- "version": "15.5.12",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.12.tgz",
- "integrity": "sha512-pUvdJN1on574wQHjaBfNGDt9Mz5utDSZFsIIQkMzPgNS8ZvT4H2mwOrOIClwsQOb6EGx5M76/CZr6G8i6pSpLg==",
+ "version": "16.1.6",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-16.1.6.tgz",
+ "integrity": "sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==",
"license": "MIT"
},
"node_modules/@next/swc-darwin-arm64": {
- "version": "15.5.12",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.12.tgz",
- "integrity": "sha512-RnRjBtH8S8eXCpUNkQ+543DUc7ys8y15VxmFU9HRqlo9BG3CcBUiwNtF8SNoi2xvGCVJq1vl2yYq+3oISBS0Zg==",
+ "version": "16.1.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.6.tgz",
+ "integrity": "sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==",
"cpu": [
"arm64"
],
@@ -2499,9 +2499,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
- "version": "15.5.12",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.12.tgz",
- "integrity": "sha512-nqa9/7iQlboF1EFtNhWxQA0rQstmYRSBGxSM6g3GxvxHxcoeqVXfGNr9stJOme674m2V7r4E3+jEhhGvSQhJRA==",
+ "version": "16.1.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.6.tgz",
+ "integrity": "sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==",
"cpu": [
"x64"
],
@@ -2515,9 +2515,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
- "version": "15.5.12",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.12.tgz",
- "integrity": "sha512-dCzAjqhDHwmoB2M4eYfVKqXs99QdQxNQVpftvP1eGVppamXh/OkDAwV737Zr0KPXEqRUMN4uCjh6mjO+XtF3Mw==",
+ "version": "16.1.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.6.tgz",
+ "integrity": "sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==",
"cpu": [
"arm64"
],
@@ -2531,9 +2531,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
- "version": "15.5.12",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.12.tgz",
- "integrity": "sha512-+fpGWvQiITgf7PUtbWY1H7qUSnBZsPPLyyq03QuAKpVoTy/QUx1JptEDTQMVvQhvizCEuNLEeghrQUyXQOekuw==",
+ "version": "16.1.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.6.tgz",
+ "integrity": "sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==",
"cpu": [
"arm64"
],
@@ -2547,9 +2547,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
- "version": "15.5.12",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.12.tgz",
- "integrity": "sha512-jSLvgdRRL/hrFAPqEjJf1fFguC719kmcptjNVDJl26BnJIpjL3KH5h6mzR4mAweociLQaqvt4UyzfbFjgAdDcw==",
+ "version": "16.1.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.6.tgz",
+ "integrity": "sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==",
"cpu": [
"x64"
],
@@ -2563,9 +2563,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
- "version": "15.5.12",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.12.tgz",
- "integrity": "sha512-/uaF0WfmYqQgLfPmN6BvULwxY0dufI2mlN2JbOKqqceZh1G4hjREyi7pg03zjfyS6eqNemHAZPSoP84x17vo6w==",
+ "version": "16.1.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.6.tgz",
+ "integrity": "sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==",
"cpu": [
"x64"
],
@@ -2579,9 +2579,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
- "version": "15.5.12",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.12.tgz",
- "integrity": "sha512-xhsL1OvQSfGmlL5RbOmU+FV120urrgFpYLq+6U8C6KIym32gZT6XF/SDE92jKzzlPWskkbjOKCpqk5m4i8PEfg==",
+ "version": "16.1.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.6.tgz",
+ "integrity": "sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==",
"cpu": [
"arm64"
],
@@ -2595,9 +2595,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
- "version": "15.5.12",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.12.tgz",
- "integrity": "sha512-Z1Dh6lhFkxvBDH1FoW6OU/L6prYwPSlwjLiZkExIAh8fbP6iI/M7iGTQAJPYJ9YFlWobCZ1PHbchFhFYb2ADkw==",
+ "version": "16.1.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.6.tgz",
+ "integrity": "sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==",
"cpu": [
"x64"
],
@@ -3322,32 +3322,24 @@
"undici-types": "~7.16.0"
}
},
- "node_modules/@types/prop-types": {
- "version": "15.7.15",
- "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
- "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@types/react": {
- "version": "18.3.28",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz",
- "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==",
+ "version": "19.2.14",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
+ "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/prop-types": "*",
"csstype": "^3.2.2"
}
},
"node_modules/@types/react-dom": {
- "version": "18.3.7",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
- "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
"dev": true,
"license": "MIT",
"peerDependencies": {
- "@types/react": "^18.0.0"
+ "@types/react": "^19.2.0"
}
},
"node_modules/@types/semver": {
@@ -4207,7 +4199,6 @@
"version": "2.9.19",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz",
"integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==",
- "dev": true,
"license": "Apache-2.0",
"bin": {
"baseline-browser-mapping": "dist/cli.js"
@@ -7659,13 +7650,14 @@
"license": "MIT"
},
"node_modules/next": {
- "version": "15.5.12",
- "resolved": "https://registry.npmjs.org/next/-/next-15.5.12.tgz",
- "integrity": "sha512-Fi/wQ4Etlrn60rz78bebG1i1SR20QxvV8tVp6iJspjLUSHcZoeUXCt+vmWoEcza85ElZzExK/jJ/F6SvtGktjA==",
+ "version": "16.1.6",
+ "resolved": "https://registry.npmjs.org/next/-/next-16.1.6.tgz",
+ "integrity": "sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==",
"license": "MIT",
"dependencies": {
- "@next/env": "15.5.12",
+ "@next/env": "16.1.6",
"@swc/helpers": "0.5.15",
+ "baseline-browser-mapping": "^2.8.3",
"caniuse-lite": "^1.0.30001579",
"postcss": "8.4.31",
"styled-jsx": "5.1.6"
@@ -7674,18 +7666,18 @@
"next": "dist/bin/next"
},
"engines": {
- "node": "^18.18.0 || ^19.8.0 || >= 20.0.0"
+ "node": ">=20.9.0"
},
"optionalDependencies": {
- "@next/swc-darwin-arm64": "15.5.12",
- "@next/swc-darwin-x64": "15.5.12",
- "@next/swc-linux-arm64-gnu": "15.5.12",
- "@next/swc-linux-arm64-musl": "15.5.12",
- "@next/swc-linux-x64-gnu": "15.5.12",
- "@next/swc-linux-x64-musl": "15.5.12",
- "@next/swc-win32-arm64-msvc": "15.5.12",
- "@next/swc-win32-x64-msvc": "15.5.12",
- "sharp": "^0.34.3"
+ "@next/swc-darwin-arm64": "16.1.6",
+ "@next/swc-darwin-x64": "16.1.6",
+ "@next/swc-linux-arm64-gnu": "16.1.6",
+ "@next/swc-linux-arm64-musl": "16.1.6",
+ "@next/swc-linux-x64-gnu": "16.1.6",
+ "@next/swc-linux-x64-musl": "16.1.6",
+ "@next/swc-win32-arm64-msvc": "16.1.6",
+ "@next/swc-win32-x64-msvc": "16.1.6",
+ "sharp": "^0.34.4"
},
"peerDependencies": {
"@opentelemetry/api": "^1.1.0",
diff --git a/package.json b/package.json
index f3ed0e0..0bef5a5 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,7 @@
"dev": "./scripts/kill-dev.sh && next dev",
"build": "next build",
"start": "next start",
- "lint": "next lint",
+ "lint": "eslint . --ext .ts,.tsx --ignore-path .gitignore",
"test": "jest",
"test:watch": "jest --watch",
"security:check": "node scripts/security/security-check.js",
@@ -20,31 +20,31 @@
"axios": "^1.6.2",
"bcryptjs": "^3.0.2",
"cheerio": "^1.1.0",
- "next": "^15.3.4",
+ "next": "^16.1.6",
"pg": "^8.16.2",
- "react": "^19.1.0",
- "react-dom": "^19.1.0"
+ "react": "^19.2.4",
+ "react-dom": "^19.2.4"
},
"devDependencies": {
- "@testing-library/jest-dom": "^6.6.3",
- "@testing-library/react": "^16.3.0",
+ "@testing-library/jest-dom": "^6.9.1",
+ "@testing-library/react": "^16.3.2",
"@types/jest": "^30.0.0",
- "@types/react": "^18.2.43",
- "@types/react-dom": "^18.2.17",
+ "@types/react": "^19.2.14",
+ "@types/react-dom": "^19.2.3",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
"@vitejs/plugin-react": "^4.2.1",
- "autoprefixer": "^10.4.16",
+ "autoprefixer": "^10.4.24",
"eslint": "^8.55.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.5",
"husky": "^9.1.7",
"jest": "^30.0.0",
"jest-environment-jsdom": "^30.0.0",
- "postcss": "^8.4.32",
+ "postcss": "^8.5.6",
"tailwindcss": "^3.3.0",
- "tsx": "^4.20.3",
- "typescript": "^5.2.2",
+ "tsx": "^4.21.0",
+ "typescript": "^5.9.3",
"vite": "^5.0.8"
}
}
diff --git a/tsconfig.json b/tsconfig.json
index 240013a..b6f715d 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "ES2017",
- "lib": ["dom", "dom.iterable", "esnext"],
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -12,7 +16,7 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
- "jsx": "preserve",
+ "jsx": "react-jsx",
"incremental": true,
"plugins": [
{
@@ -20,9 +24,19 @@
}
],
"paths": {
- "@/*": ["./*"]
+ "@/*": [
+ "./*"
+ ]
}
},
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
- "exclude": ["node_modules"]
-}
\ No newline at end of file
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts",
+ ".next/dev/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}