-
Notifications
You must be signed in to change notification settings - Fork 1
Development Guide
npm run devVite starts a local server at http://localhost:5173 with hot-module replacement. Most changes are reflected immediately without a browser reload.
| Script | Command | Description |
|---|---|---|
| Dev server | npm run dev |
Start local development server (HMR) |
| Production build | npm run build |
Type-check then bundle for production |
| Preview build | npm run preview |
Serve the dist/ folder locally |
| Type-check | npm run typecheck |
Run tsc --noEmit — no output means success |
| Lint | npm run lint |
Run ESLint over src/
|
| Test (once) | npm run test |
Run Vitest in run mode (no watch) |
| Test (UI) | npm run test:ui |
Open Vitest browser UI for interactive testing |
| Coverage | npm run coverage |
Run tests and generate a coverage report |
The project uses Vitest with Testing Library and jsdom.
# Run the full test suite once
npm run test
# Interactive browser UI (great for debugging a specific test)
npm run test:ui
# Coverage report (output in coverage/)
npm run coverageTests are co-located with the source files they test, inside __tests__/ subdirectories. Open coverage/index.html in a browser to browse the detailed line-by-line coverage report.
- Use
src/test-utils/renderWithProviders.tsxto render components that need React Context (AppContext, ToastContext). - Mock browser APIs (localStorage, Speech Recognition) at the top of the test file, not inside individual tests.
- Keep tests focused: one behaviour per
it()block.
ESLint is configured in eslint.config.js with:
-
typescript-eslintfor TypeScript-aware rules -
eslint-plugin-react-hooksto enforce the Rules of Hooks -
eslint-plugin-react-refreshto catch patterns that break Vite HMR
npm run lintFix auto-fixable issues:
npx eslint src --fixnpm run typecheckRuns tsc --noEmit against the full project. No output means no type errors. The CI pipeline runs this before the test suite on every push and pull request.
The project targets ES2022 with strict mode enabled. All new code should be fully typed — avoid any.
src/
├── components/ # Reusable UI components, each with an __tests__/ folder
├── pages/ # Top-level route components
├── context/ # React Context (global state: rubrics, students, grades)
├── hooks/ # Custom React hooks
├── services/ # External integrations (Standards API, Microsoft Graph)
├── store/ # localStorage persistence layer
├── utils/ # Pure utility functions (grade calc, PDF/DOCX export, OCR)
├── types/ # Shared TypeScript type definitions
├── data/ # Static data (CEFR descriptors, VO tracks, templates)
└── locales/ # i18n translation files (en.json, nl.json)
See Architecture for a detailed breakdown.
GitHub Actions runs on every push and pull request to main:
-
Type-check —
npm run typecheck -
Lint —
npm run lint -
Test with coverage —
npm run coverage
The coverage report is uploaded as an artifact and retained for 14 days. A pull request is expected to keep all three checks green.
If you want to develop or test the Supabase sync feature:
# Start the local Supabase stack (requires Docker Desktop)
supabase start
# The CLI prints a local URL + anon key.
# Paste them into Settings → Database → Connect & Sync,
# or add them to .env.local:
# VITE_SUPABASE_URL=http://127.0.0.1:54321
# VITE_SUPABASE_ANON_KEY=<printed-key>Browse the local database at http://127.0.0.1:54323 (Supabase Studio).
# Stop the local stack when done
supabase stopSee the Supabase Sync page for cloud setup and the full migration reference.
All application state lives in AppContext (src/context/AppContext.tsx). It reads from and writes to localStorage via src/store/storage.ts.
- Read state with
useContext(AppContext)(or theuseAppContexthelper hook). - Dispatch actions through the context's provided setter functions — do not write to
localStoragedirectly from components. - For tests, use
renderWithProviderswhich wraps the component in a pre-seededAppContext.
- Create
src/pages/MyPage.tsx. - Add the route in
src/App.tsxinside the<Routes>block. - Add a navigation entry in
src/components/Layout/Sidebar.tsx(and optionallyTopbar.tsx). - Add translation keys for the page title and any UI strings in
src/locales/en.jsonandsrc/locales/nl.json.