diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ddea393..d714b74 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -92,8 +92,7 @@ jobs:
- name: Run type checking
run: |
cd frontend
- echo "Skipping TypeScript type checking for now - will fix type issues in a separate PR"
- # npx tsc --noEmit
+ npx tsc --noEmit
- name: Run tests
run: |
@@ -137,8 +136,7 @@ jobs:
- name: Run npm audit
run: |
cd frontend
- echo "Skipping npm audit for now - will address security issues in a separate PR"
- # npm audit --audit-level=moderate
+ npm audit --audit-level=moderate
dependency-check:
runs-on: ubuntu-latest
diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js
index 05331ec..92dcc6a 100644
--- a/frontend/eslint.config.js
+++ b/frontend/eslint.config.js
@@ -1,6 +1,8 @@
import js from '@eslint/js'
import typescript from '@typescript-eslint/eslint-plugin'
import typescriptParser from '@typescript-eslint/parser'
+import reactHooks from 'eslint-plugin-react-hooks'
+import reactRefresh from 'eslint-plugin-react-refresh'
export default [
js.configs.recommended,
@@ -28,11 +30,16 @@ export default [
}
},
plugins: {
- '@typescript-eslint': typescript
+ '@typescript-eslint': typescript,
+ 'react-hooks': reactHooks,
+ 'react-refresh': reactRefresh
},
rules: {
'no-unused-vars': 'off',
- '@typescript-eslint/no-unused-vars': 'warn'
+ '@typescript-eslint/no-unused-vars': 'warn',
+ 'react-hooks/rules-of-hooks': 'error',
+ 'react-hooks/exhaustive-deps': 'warn',
+ 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }]
}
},
{
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 8cc7881..49ae185 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -12,7 +12,6 @@
"axios": "^1.13.2",
"react": "^19.2.5",
"react-dom": "^19.2.5",
- "react-router-dom": "^7.14.2",
"tailwindcss": "^4.1.17"
},
"devDependencies": {
@@ -25,7 +24,6 @@
"@typescript-eslint/parser": "^8.59.1",
"@vitejs/plugin-react": "^6.0.1",
"@vitest/coverage-v8": "^4.0.10",
- "autoprefixer": "^10.4.16",
"eslint": "^10.2.1",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.2",
@@ -2077,43 +2075,6 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
- "node_modules/autoprefixer": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz",
- "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/autoprefixer"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "browserslist": "^4.28.2",
- "caniuse-lite": "^1.0.30001787",
- "fraction.js": "^5.3.4",
- "picocolors": "^1.1.1",
- "postcss-value-parser": "^4.2.0"
- },
- "bin": {
- "autoprefixer": "bin/autoprefixer"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- },
- "peerDependencies": {
- "postcss": "^8.1.0"
- }
- },
"node_modules/axios": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.15.2.tgz",
@@ -2268,19 +2229,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/cookie": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
- "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -2874,20 +2822,6 @@
"node": ">= 6"
}
},
- "node_modules/fraction.js": {
- "version": "5.3.4",
- "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
- "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "*"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/rawify"
- }
- },
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@@ -3892,13 +3826,6 @@
"node": "^10 || ^12 || >=14"
}
},
- "node_modules/postcss-value-parser": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -3973,44 +3900,6 @@
"license": "MIT",
"peer": true
},
- "node_modules/react-router": {
- "version": "7.14.2",
- "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.14.2.tgz",
- "integrity": "sha512-yCqNne6I8IB6rVCH7XUvlBK7/QKyqypBFGv+8dj4QBFJiiRX+FG7/nkdAvGElyvVZ/HQP5N19wzteuTARXi5Gw==",
- "license": "MIT",
- "dependencies": {
- "cookie": "^1.0.1",
- "set-cookie-parser": "^2.6.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "react": ">=18",
- "react-dom": ">=18"
- },
- "peerDependenciesMeta": {
- "react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/react-router-dom": {
- "version": "7.14.2",
- "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.14.2.tgz",
- "integrity": "sha512-YZcM5ES8jJSM+KrJ9BdvHHqlnGTg5tH3sC5ChFRj4inosKctdyzBDhOyyHdGk597q2OT6NTrCA1OvB/YDwfekQ==",
- "license": "MIT",
- "dependencies": {
- "react-router": "7.14.2"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "react": ">=18",
- "react-dom": ">=18"
- }
- },
"node_modules/redent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
@@ -4108,12 +3997,6 @@
"node": ">=10"
}
},
- "node_modules/set-cookie-parser": {
- "version": "2.7.2",
- "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
- "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
- "license": "MIT"
- },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 1ae94e0..4bba2e9 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -18,7 +18,6 @@
"axios": "^1.13.2",
"react": "^19.2.5",
"react-dom": "^19.2.5",
- "react-router-dom": "^7.14.2",
"tailwindcss": "^4.1.17"
},
"devDependencies": {
@@ -31,7 +30,6 @@
"@typescript-eslint/parser": "^8.59.1",
"@vitejs/plugin-react": "^6.0.1",
"@vitest/coverage-v8": "^4.0.10",
- "autoprefixer": "^10.4.16",
"eslint": "^10.2.1",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.2",
diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js
index 1c87846..a7f73a2 100644
--- a/frontend/postcss.config.js
+++ b/frontend/postcss.config.js
@@ -1,6 +1,5 @@
export default {
plugins: {
'@tailwindcss/postcss': {},
- autoprefixer: {},
},
}
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx
index 3d7150d..6f4ac9b 100644
--- a/frontend/src/main.tsx
+++ b/frontend/src/main.tsx
@@ -1,10 +1,10 @@
-import React from 'react'
-import ReactDOM from 'react-dom/client'
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
import App from './App.tsx'
import './index.css'
-ReactDOM.createRoot(document.getElementById('root')!).render(
-
+createRoot(document.getElementById('root')!).render(
+
- ,
+ ,
)
diff --git a/frontend/src/services/api.ts b/frontend/src/services/api.ts
index eae62d1..90c8629 100644
--- a/frontend/src/services/api.ts
+++ b/frontend/src/services/api.ts
@@ -9,7 +9,7 @@ import type {
ScriptureSearch
} from '../types/scripture';
-const API_BASE_URL = (import.meta as any).env?.VITE_API_URL || 'http://localhost:8000';
+const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000';
const api = axios.create({
baseURL: API_BASE_URL,
diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts
index 11f02fe..b54b4c9 100644
--- a/frontend/src/vite-env.d.ts
+++ b/frontend/src/vite-env.d.ts
@@ -1 +1,9 @@
///
+
+interface ImportMetaEnv {
+ readonly VITE_API_URL: string
+}
+
+interface ImportMeta {
+ readonly env: ImportMetaEnv
+}
diff --git a/frontend/vite-env.d.ts b/frontend/vite-env.d.ts
deleted file mode 100644
index b54b4c9..0000000
--- a/frontend/vite-env.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-///
-
-interface ImportMetaEnv {
- readonly VITE_API_URL: string
-}
-
-interface ImportMeta {
- readonly env: ImportMetaEnv
-}