diff --git a/.eslintrc b/.eslintrc index af7fa28f..402a51d8 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,5 @@ { - "extends": ["react-app"], + "extends": ["react-app", "plugin:@tanstack/eslint-plugin-router/recommended"], "parser": "@typescript-eslint/parser", "plugins": ["react-hooks"] } diff --git a/package.json b/package.json index d787e607..d45bc64f 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ "dev:backend": "convex dev --tail-logs", "build": "vite build", "start": "vite start", - "lint": "prettier --check '**/*' --ignore-unknown && eslint --ext .ts,.tsx ./src", - "format": "prettier --write '**/*' --ignore-unknown", + "lint": "prettier --check 'src/**/*' --ignore-unknown && eslint --ext .ts,.tsx ./src", + "format": "prettier --write 'src/**/*' --ignore-unknown", "linkAll": "node scripts/link.js" }, "dependencies": { @@ -88,6 +88,7 @@ "@content-collections/core": "^0.8.2", "@content-collections/vite": "^0.2.4", "@shikijs/transformers": "^1.10.3", + "@tanstack/eslint-plugin-router": "^1.131.2", "@types/node": "^24.3.0", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 518e8b7e..6a8c05ec 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -216,6 +216,9 @@ importers: '@shikijs/transformers': specifier: ^1.10.3 version: 1.10.3 + '@tanstack/eslint-plugin-router': + specifier: ^1.131.2 + version: 1.131.2(eslint@8.57.0)(typescript@5.6.3) '@types/node': specifier: ^24.3.0 version: 24.3.0 @@ -1929,6 +1932,12 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/eslint-utils@4.7.0': + resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/regexpp@4.10.0': resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -3579,6 +3588,11 @@ packages: peerDependencies: vite: '>=6.0.0' + '@tanstack/eslint-plugin-router@1.131.2': + resolution: {integrity: sha512-f0x2+MqVnfo+0z+HhAnJYoFbRRGcuc9W4p662Qsgi/z6KCFj1/HCQdorcZ3C8yjYAOsLd8zJivY1YnPbcJE+Yg==} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + '@tanstack/history@1.131.2': resolution: {integrity: sha512-cs1WKawpXIe+vSTeiZUuSBy8JFjEuDgdMKZFRLKwQysKo8y2q6Q1HvS74Yw+m5IhOW1nTZooa6rlgdfXcgFAaw==} engines: {node: '>=12'} @@ -4004,6 +4018,12 @@ packages: typescript: optional: true + '@typescript-eslint/project-service@8.39.1': + resolution: {integrity: sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/project-service@8.40.0': resolution: {integrity: sha512-/A89vz7Wf5DEXsGVvcGdYKbVM9F7DyFXj52lNYUDS1L9yJfqjW/fIp5PgMuEJL/KeqVTe2QSbXAGUZljDUpArw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4018,6 +4038,16 @@ packages: resolution: {integrity: sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==} engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/scope-manager@8.39.1': + resolution: {integrity: sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.39.1': + resolution: {integrity: sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/tsconfig-utils@8.40.0': resolution: {integrity: sha512-jtMytmUaG9d/9kqSl/W3E3xaWESo4hFDxAIHGVW/WKKtQhesnRIJSAJO6XckluuJ6KDB5woD1EiqknriCtAmcw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4042,6 +4072,10 @@ packages: resolution: {integrity: sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==} engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/types@8.39.1': + resolution: {integrity: sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.40.0': resolution: {integrity: sha512-ETdbFlgbAmXHyFPwqUIYrfc12ArvpBhEVgGAxVYSwli26dn8Ko+lIo4Su9vI9ykTZdJn+vJprs/0eZU0YMAEQg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4064,6 +4098,12 @@ packages: typescript: optional: true + '@typescript-eslint/typescript-estree@8.39.1': + resolution: {integrity: sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/typescript-estree@8.40.0': resolution: {integrity: sha512-k1z9+GJReVVOkc1WfVKs1vBrR5MIKKbdAjDTPvIK3L8De6KbFfPFt6BKpdkdk7rZS2GtC/m6yI5MYX+UsuvVYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4076,6 +4116,13 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + '@typescript-eslint/utils@8.39.1': + resolution: {integrity: sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/visitor-keys@5.62.0': resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4084,6 +4131,10 @@ packages: resolution: {integrity: sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==} engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/visitor-keys@8.39.1': + resolution: {integrity: sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.40.0': resolution: {integrity: sha512-8CZ47QwalyRjsypfwnbI3hKy5gJDPmrkLjkgMxhi0+DZZ2QNx2naS6/hWoVYUHU7LU2zleF68V9miaVZvhFfTA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4490,9 +4541,6 @@ packages: brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} @@ -10304,6 +10352,11 @@ snapshots: eslint: 8.57.0 eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils@4.7.0(eslint@8.57.0)': + dependencies: + eslint: 8.57.0 + eslint-visitor-keys: 3.4.3 + '@eslint-community/regexpp@4.10.0': {} '@eslint/eslintrc@2.1.4': @@ -11978,6 +12031,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@tanstack/eslint-plugin-router@1.131.2(eslint@8.57.0)(typescript@5.6.3)': + dependencies: + '@typescript-eslint/utils': 8.39.1(eslint@8.57.0)(typescript@5.6.3) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + '@tanstack/history@1.131.2': {} '@tanstack/pacer@0.7.0': {} @@ -12611,6 +12672,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/project-service@8.39.1(typescript@5.6.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.39.1(typescript@5.6.3) + '@typescript-eslint/types': 8.39.1 + debug: 4.4.1 + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/project-service@8.40.0(typescript@5.9.2)': dependencies: '@typescript-eslint/tsconfig-utils': 8.40.0(typescript@5.9.2) @@ -12630,6 +12700,15 @@ snapshots: '@typescript-eslint/types': 7.2.0 '@typescript-eslint/visitor-keys': 7.2.0 + '@typescript-eslint/scope-manager@8.39.1': + dependencies: + '@typescript-eslint/types': 8.39.1 + '@typescript-eslint/visitor-keys': 8.39.1 + + '@typescript-eslint/tsconfig-utils@8.39.1(typescript@5.6.3)': + dependencies: + typescript: 5.6.3 + '@typescript-eslint/tsconfig-utils@8.40.0(typescript@5.9.2)': dependencies: typescript: 5.9.2 @@ -12650,6 +12729,8 @@ snapshots: '@typescript-eslint/types@7.2.0': {} + '@typescript-eslint/types@8.39.1': {} + '@typescript-eslint/types@8.40.0': {} '@typescript-eslint/typescript-estree@5.62.0(typescript@5.6.3)': @@ -12681,6 +12762,22 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.39.1(typescript@5.6.3)': + dependencies: + '@typescript-eslint/project-service': 8.39.1(typescript@5.6.3) + '@typescript-eslint/tsconfig-utils': 8.39.1(typescript@5.6.3) + '@typescript-eslint/types': 8.39.1 + '@typescript-eslint/visitor-keys': 8.39.1 + debug: 4.4.1 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.6.3) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/typescript-estree@8.40.0(typescript@5.9.2)': dependencies: '@typescript-eslint/project-service': 8.40.0(typescript@5.9.2) @@ -12712,6 +12809,17 @@ snapshots: - supports-color - typescript + '@typescript-eslint/utils@8.39.1(eslint@8.57.0)(typescript@5.6.3)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@8.57.0) + '@typescript-eslint/scope-manager': 8.39.1 + '@typescript-eslint/types': 8.39.1 + '@typescript-eslint/typescript-estree': 8.39.1(typescript@5.6.3) + eslint: 8.57.0 + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/visitor-keys@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -12722,6 +12830,11 @@ snapshots: '@typescript-eslint/types': 7.2.0 eslint-visitor-keys: 3.4.3 + '@typescript-eslint/visitor-keys@8.39.1': + dependencies: + '@typescript-eslint/types': 8.39.1 + eslint-visitor-keys: 4.2.1 + '@typescript-eslint/visitor-keys@8.40.0': dependencies: '@typescript-eslint/types': 8.40.0 @@ -13269,10 +13382,6 @@ snapshots: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.0.1: - dependencies: - balanced-match: 1.0.2 - brace-expansion@2.0.2: dependencies: balanced-match: 1.0.2 @@ -15679,11 +15788,11 @@ snapshots: minimatch@8.0.4: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minimatch@9.0.3: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minimatch@9.0.5: dependencies: @@ -17153,6 +17262,10 @@ snapshots: dependencies: typescript: 5.6.3 + ts-api-utils@2.1.0(typescript@5.6.3): + dependencies: + typescript: 5.6.3 + ts-api-utils@2.1.0(typescript@5.9.2): dependencies: typescript: 5.9.2 diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index 21bb1ae4..849aa486 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -38,6 +38,24 @@ export const Route = createRootRouteWithContext<{ convexQueryClient: ConvexQueryClient ensureUser: () => Promise }>()({ + beforeLoad: async (ctx) => { + if ( + ctx.location.href.match(/\/docs\/(react|vue|angular|svelte|solid)\//gm) + ) { + throw redirect({ + href: ctx.location.href.replace( + /\/docs\/(react|vue|angular|svelte|solid)\//gm, + '/docs/framework/$1/' + ), + }) + } + + // // During SSR only (the only time serverHttpClient exists), + // // set the auth token for Convex to make HTTP queries with. + // if (token) { + // ctx.context.convexQueryClient.serverHttpClient?.setAuth(token) + // } + }, head: () => ({ meta: [ { @@ -123,24 +141,6 @@ export const Route = createRootRouteWithContext<{ }, ], }), - beforeLoad: async (ctx) => { - if ( - ctx.location.href.match(/\/docs\/(react|vue|angular|svelte|solid)\//gm) - ) { - throw redirect({ - href: ctx.location.href.replace( - /\/docs\/(react|vue|angular|svelte|solid)\//gm, - '/docs/framework/$1/' - ), - }) - } - - // // During SSR only (the only time serverHttpClient exists), - // // set the auth token for Convex to make HTTP queries with. - // if (token) { - // ctx.context.convexQueryClient.serverHttpClient?.setAuth(token) - // } - }, staleTime: Infinity, errorComponent: (props) => { return ( diff --git a/src/styles/app.css b/src/styles/app.css index f10d1b11..fa7d305e 100644 --- a/src/styles/app.css +++ b/src/styles/app.css @@ -735,4 +735,4 @@ mark { font-style: italic; font-weight: 900; src: url('/fonts/inter-v19-latin-900italic.woff2') format('woff2'); -} \ No newline at end of file +}