The frontend for the CV Management and Deterministic Internship Candidate Filtering System. It gives University of Ruhuna students a structured workspace for maintaining career information and generating CVs, while giving administrators tools for academic-data management, internship requests, deterministic candidate filtering, shortlisting, and exports.
This is a role-aware single-page application built with React, TypeScript, and Vite. It can run against the CV Management API or use deterministic Mock Service Worker (MSW) handlers for local development and browser testing.
This repository contains only the web frontend. A compatible backend is required for live data, authentication, file processing, PDF generation, and export jobs.
- Key capabilities
- Technology stack
- System architecture
- Getting started
- Environment configuration
- Available scripts
- Application routes
- API integration
- Testing
- Project structure
- Development conventions
- Production build and deployment
- Troubleshooting
- Contributing
- License
- Student registration, OTP verification, login, and password recovery
- Dashboard with profile and CV-readiness information
- Personal, contact, experience, certificate, award, and activity management
- Profile-photo and certificate-evidence uploads
- Declared-skill management using the shared skill taxonomy
- Project management with repository/demo links and skill associations
- Read-only official academic records and GPA summary
- Record-level CV content selection
- Sanitized HTML CV preview, freshness tracking, saved versions, and PDF download
- Administrator authentication and password recovery
- Operational dashboard metrics
- Academic-ledger CSV upload, processing, staged-row inspection, validation, and transactional commit
- Registered-student search, filtering, sorting, and pagination
- Read-only student deep dives and latest saved CV access
- Company and internship-request management
- Required-skill selection from the shared taxonomy
- Deterministic candidate filtering using official GPA bounds and declared skills
- Manual candidate selection without ranking, scoring, probability, or automated recommendations
- Draft and finalized shortlist workflows with guidance acknowledgement
- Shortlist summary export as CSV
- Bulk export of available latest CVs as ZIP, including explicit reporting for missing CVs
- Role-protected and public-only routes
- Lazy-loaded feature pages with route-specific skeletons
- Responsive desktop, tablet, and mobile layouts
- Light and dark themes
- Reduced-motion support
- Accessible forms, dialogs, feedback, and keyboard interactions
- URL-backed list filters and pagination where applicable
- Centralized loading, empty, error, notification, and overlay patterns
- Strict runtime response validation with Zod
- Deterministic API mocks for local development and automated tests
| Area | Technology | Purpose |
|---|---|---|
| UI | React 19 | Component-based application UI |
| Language | TypeScript 5.7 | Strict static typing |
| Build tooling | Vite 6 | Development server and optimized production builds |
| Routing | React Router 7 | Nested layouts, guarded routes, and fallbacks |
| Server state | TanStack Query 5 | Fetching, caching, invalidation, and mutation state |
| Validation | Zod 3 | Runtime API and form-data validation |
| Security | DOMPurify | Sanitization of server-generated CV preview HTML |
| API mocking | MSW 2 | Browser and test request interception |
| Unit/integration testing | Vitest, Testing Library, jsdom | Component, hook, schema, mapper, and API tests |
| End-to-end testing | Playwright | Browser workflows, accessibility, and visual regression |
| Quality | ESLint, Prettier, TypeScript | Static analysis and formatting |
| CI | GitHub Actions | Quality gates, cross-browser tests, and preview artifacts |
The application follows a feature-oriented architecture with a small application shell and reusable shared infrastructure.
Browser
|
v
React Router + guarded layouts
|
+-- Student feature modules
+-- Administrator feature modules
|
v
TanStack Query hooks + feature API modules
|
+-- Zod runtime validation
+-- request/error/file-download utilities
|
v
CV Management API (/api/v1)
The primary architectural boundaries are:
src/app— bootstrap, providers, runtime configuration, layouts, route definitions, and guards.src/features— domain-owned pages, components, hooks, schemas, mappers, types, API wrappers, and focused tests.src/shared— reusable API, authentication, UI, accessibility, validation, error, notification, overlay, skeleton, and skill-taxonomy infrastructure.src/mocks— MSW handlers and deterministic fixtures for local and automated environments.docs/api— the canonical OpenAPI contract and its validation/traceability artifacts.
Client-only state is kept close to the component or in focused providers. Remote server state is managed through TanStack Query. Feature query keys include all server-affecting inputs so caching and invalidation remain deterministic.
- Node.js 22.x (the version used by CI)
- npm (included with Node.js)
- Git
- A running compatible backend on
http://localhost:8080for live integration, or local API mocks enabled for standalone frontend development
git clone https://github.com/UOR-Internship-Management-System/frontend.git
cd frontendUse npm ci for a clean, lockfile-reproducible installation:
npm cicp .env.example .env.localOn PowerShell:
Copy-Item .env.example .env.localChoose one of the following configurations.
VITE_APP_ENV=development
VITE_API_BASE_URL=/api/v1
VITE_ENABLE_API_MOCKS=false
VITE_DEV_AUTH_ROLE=During development, Vite proxies /api/* requests to http://localhost:8080.
VITE_APP_ENV=development
VITE_API_BASE_URL=/api/v1
VITE_ENABLE_API_MOCKS=true
VITE_DEV_AUTH_ROLE=Mock mode is intentionally disabled in production builds. The local mock accounts are:
| Role | Password | |
|---|---|---|
| Student | student@dcs.ruh.ac.lk |
Password@123 |
| Administrator | admin@dcs.ruh.ac.lk |
Password@123 |
These credentials are development fixtures only and must never be used in a deployed environment.
npm run devOpen http://localhost:5173. Vite provides hot module replacement while files are edited.
npm run validate-env
npm run typecheck
npm run test
npm run buildOnly variables prefixed with VITE_ are exposed to browser code. Never store secrets, database credentials, private tokens, or backend-only configuration in these variables.
| Variable | Allowed values | Default | Description |
|---|---|---|---|
VITE_APP_ENV |
development, test, staging, production |
Vite mode / development |
Logical application environment. |
VITE_API_BASE_URL |
Relative path or http(s) URL |
/api/v1 |
Base URL used by feature API modules. A trailing slash is normalized. |
VITE_ENABLE_API_MOCKS |
true, false |
false |
Starts the MSW browser worker outside production. Unhandled requests pass through. |
VITE_DEV_AUTH_ROLE |
empty, STUDENT, ADMIN |
empty | Optional non-production development role override. It is rejected for production. |
Run npm run validate-env after changing configuration. This checks values independently of starting the application.
With the default relative API URL, the development server applies this proxy:
http://localhost:5173/api/* -> http://localhost:8080/api/*
To use another backend without the proxy, provide its full API URL:
VITE_API_BASE_URL=https://api.example.edu/api/v1The backend must then allow requests from the frontend origin and correctly handle authentication and content-disposition headers for downloads.
| Command | Description |
|---|---|
npm run dev |
Start the Vite development server on port 5173. |
npm run build |
Run the TypeScript project build and generate the optimized dist/ bundle. |
npm run preview |
Serve the production bundle locally for final inspection. |
npm run validate-env |
Validate supported frontend environment values. |
| Command | Description |
|---|---|
npm run lint |
Run ESLint across the repository. |
npm run typecheck |
Type-check all TypeScript projects without emitting application code. |
npm run format |
Format supported files with Prettier. |
npm run format:check |
Check formatting without modifying files. |
| Command | Description |
|---|---|
npm test |
Run the Vitest unit and integration suite. |
npm run test:coverage |
Run Vitest with V8 coverage. |
npm run e2e |
Run the complete Playwright suite. |
npm run e2e:cross-browser |
Run functional E2E tests in Chromium, Firefox, WebKit, and Edge. |
npm run e2e:visual |
Run responsive light/dark/reduced-motion visual regression tests. |
npm run e2e:motion |
Run motion and accessibility-focused browser tests. |
npm run e2e:internships:live |
Test internship management against a live backend. |
npm run e2e:candidate-filtering:live |
Test candidate filtering against a live backend. |
npm run e2e:shortlists-live |
Test shortlist and export flows against a live backend. |
npm run e2e:cv-live |
Test CV generation against a live backend. |
| Command | Description |
|---|---|
npm run openapi:check |
Verify the OpenAPI checksum, locked operation IDs, required artifacts, generated metadata, and scope rules. |
npm run openapi:generate |
Regenerate deterministic contract metadata and selected transport types. |
npm run verify:scope |
Scan for features and terminology excluded by the approved scope. |
Routes are declared centrally in src/app/config/routePaths.ts and registered in src/app/router/routes.tsx.
| Route | Purpose |
|---|---|
/ |
Public gateway and role selection. |
/student/sign-up |
Student registration. |
/student/verify-otp |
Student account verification. |
/student/create-password |
Initial student password creation. |
/student/login |
Student sign-in. |
/student/forgot-password |
Start student password recovery. |
/student/reset/verify-otp |
Verify a student password-reset OTP. |
/student/reset/create-password |
Complete a student password reset. |
/admin/login |
Administrator sign-in. |
/admin/forgot-password |
Start administrator password recovery. |
/admin/verify-reset-otp |
Verify an administrator password-reset OTP. |
/admin/create-password |
Complete an administrator password reset. |
| Route | Purpose |
|---|---|
/student/dashboard |
Student overview. |
/student/profile |
Profile and CV supporting information. |
/student/skills |
Declared skills and competency levels. |
/student/projects |
Project portfolio management. |
/student/cv-builder |
CV configuration, preview, save, freshness, and download. |
/student/academic-records |
Official records and GPA summary. |
| Route | Purpose |
|---|---|
/admin/dashboard |
Administrative metrics. |
/admin/academic-ledger |
Ledger upload, validation, inspection, and commit. |
/admin/students |
Registered-student directory. |
/admin/students/:studentId |
Read-only student detail workspace. |
/admin/internships |
Company and internship-request management. |
/admin/candidate-filtering |
Deterministic candidate filtering and selection. |
/admin/shortlists |
Shortlist management, finalization, and exports. |
Unauthorized access resolves to /unauthorized; unmatched paths render the not-found fallback.
The frontend's transport authority is the OpenAPI 3.1.1 contract:
docs/api/CV_Management_API_OpenAPI_v1.6.0.yaml
The contract currently reports API version 1.6.0. Its checksum and operation IDs are locked by npm run openapi:check.
Generated files under src/shared/api/generated/ contain deterministic metadata and selected transport types; they are not a complete generated SDK. Do not edit them manually. Feature-owned API modules remain responsible for HTTP and file-transfer orchestration, while feature-owned Zod schemas validate runtime responses.
When the API contract changes:
- Update the canonical OpenAPI document and its validation/traceability artifacts.
- Update the checksum and operation lock only as part of an approved contract change.
- Run
npm run openapi:generate. - Synchronize feature schemas, types, API wrappers, mappers, MSW handlers, and tests.
- Run
npm run openapi:checkand the complete quality suite.
- Access tokens are kept in
sessionStorage, so they do not persist across browser sessions. - Route guards distinguish student, administrator, public-only, verification-context, and reset-context access.
- API failures are normalized through shared error mapping and safe user-facing messages.
- Optimistic concurrency versions are sent where the contract requires them.
- Server-provided CV preview HTML is sanitized with a strict DOMPurify allowlist before rendering.
- File downloads use shared utilities and contract-defined response formats.
Vitest runs in jsdom and uses Testing Library, jest-dom matchers, MSW, and shared provider-aware render helpers. Tests live beside their feature code and under src/test for shared foundations.
npm testUse coverage when reviewing broader changes:
npm run test:coverageInstall the Playwright browsers once after dependency installation:
npx playwright installOn Linux CI or a fresh Linux development environment:
npx playwright install --with-deps chromium firefox webkitThe default Playwright configuration starts an isolated Vite server on 127.0.0.1:5174. It covers functional workflows plus responsive, theme, reduced-motion, and skeleton-state screenshots.
npm run e2eFailure artifacts are written to test-results/ and reports to playwright-report/; both are ignored by Git.
Live suites require a backend running against isolated, disposable test data. Copy the template and replace every placeholder:
cp .env.e2e-live.example .env.e2e-live.localOn PowerShell:
Copy-Item .env.e2e-live.example .env.e2e-live.localThe local file can configure:
CV_E2E_BACKEND_ORIGINCV_E2E_ADMIN_EMAILCV_E2E_ADMIN_PASSWORDCV_E2E_FINALIZED_SHORTLIST_IDCV_E2E_FILTER_REQUEST_IDCV_E2E_FILTER_SEARCH
The *.local suffix keeps real credentials and environment-specific identifiers out of version control.
frontend/
|-- .github/workflows/ # CI and preview-build workflows
|-- docs/
| |-- api/ # OpenAPI contract and contract evidence
| |-- architecture/ # Architecture and routing notes
| |-- implementation/ # Sprint implementation and validation records
| `-- testing/ # Acceptance-test evidence
|-- e2e/ # Mocked functional, visual, and accessibility tests
|-- e2e-live/ # Browser tests against a running backend
|-- public/ # Static assets, icons, PWA manifest, and MSW worker
|-- scripts/ # Environment, contract, generation, and scope checks
|-- src/
| |-- app/
| | |-- config/ # Environment, query client, flags, and route paths
| | |-- layouts/ # Root, auth, student, and admin layouts
| | |-- providers/ # Application-wide provider composition
| | `-- router/ # Routes, lazy imports, guards, and fallbacks
| |-- features/ # Domain modules grouped by business capability
| |-- mocks/ # MSW browser/server setup, handlers, and fixtures
| |-- shared/ # Reusable platform infrastructure and UI
| |-- styles/ # Tokens, themes, responsive rules, and print styles
| `-- test/ # Test setup and reusable test utilities
|-- package.json
|-- playwright.config.ts
|-- vite.config.ts
`-- vitest.config.mjs
A typical feature module contains only the layers it needs:
src/features/example/
|-- api/ # Network boundary
|-- components/ # Feature-specific UI
|-- hooks/ # Queries, mutations, and local orchestration
|-- mappers/ # API-to-view-model transformations
|-- pages/ # Route-level components
|-- schemas/ # Runtime validation
|-- tests/ # Unit and integration tests
|-- types/ # Feature types
`-- index.ts # Public feature exports
- Keep domain code inside the relevant
src/features/<feature>module. - Put only genuinely cross-feature primitives in
src/shared. - Validate external data at the API boundary with Zod.
- Map transport data into UI-friendly types when their shapes differ.
- Include every server-affecting input in TanStack Query keys.
- Invalidate dependent queries after successful mutations.
- Keep list search, filters, sorting, and pagination in the URL when the view is shareable.
- Add loading, empty, recoverable-error, and permission states.
- Add focused tests and update browser coverage for user-visible workflows.
- Run the relevant quality and contract checks before opening a pull request.
- TypeScript strict mode is enabled.
- React components and pages use
PascalCasefilenames. - Hooks use the
use...convention. - Feature query-key factories live close to their hooks.
- Generated API files must be regenerated, never hand-edited.
- Run Prettier and ESLint before committing.
Changes should preserve:
- Semantic labels, validation messages, and keyboard navigation
- Focus trapping/restoration in overlays
- Visible focus states and sufficient color contrast
- Reduced-motion behavior
- Light and dark themes
- Desktop, tablet, and mobile layouts
- Stable skeleton and content geometry where visual tests cover the page
Create an optimized bundle:
npm run buildThe output is written to dist/. Inspect it locally with:
npm run previewThe application is a client-rendered SPA and can be hosted by any static web server or CDN. A production deployment must:
- Build with
VITE_APP_ENV=production. - Provide the production API base URL at build time.
- Keep
VITE_ENABLE_API_MOCKS=falseandVITE_DEV_AUTH_ROLEempty. - Serve
index.htmlfor unknown non-asset paths so deep links work with React Router. - Serve assets from
dist/with appropriate caching and compression. - Configure HTTPS, API CORS or a same-origin reverse proxy, and secure backend authentication.
- Avoid long-lived caching for
index.htmlso new asset manifests are discovered promptly.
Example production variables:
VITE_APP_ENV=production
VITE_API_BASE_URL=https://api.example.edu/api/v1
VITE_ENABLE_API_MOCKS=false
VITE_DEV_AUTH_ROLE=Pull requests also run the Frontend Preview Build workflow, which uploads the generated dist/ directory as a GitHub Actions artifact.
The main GitHub Actions quality workflow runs:
- Reproducible dependency installation
- Environment validation
- Prettier formatting check
- ESLint
- TypeScript checking
- Vitest
- Production build
- Playwright visual and motion baselines
- Cross-browser E2E tests
- OpenAPI synchronization checks
- Removed-scope guardrails
Before pushing a substantial change, reproduce the core gates locally:
npm run validate-env
npm run format:check
npm run lint
npm run typecheck
npm test
npm run build
npm run openapi:check
npm run verify:scope- Confirm the backend is listening on
http://localhost:8080when using the default proxy. - Verify
VITE_API_BASE_URLincludes/api/v1. - Restart Vite after changing an environment file.
- If using a full remote URL, check the backend's CORS configuration.
- Use
VITE_ENABLE_API_MOCKS=trueto work without a backend.
- Ensure
public/mockServiceWorker.jsexists. - Use a non-production
VITE_APP_ENV. - Set the value exactly to
true(lowercase). - Check the browser console for service-worker registration errors.
- Sign in with the role that owns the route.
- Remember that authentication is stored in
sessionStorage; a new browser session requires a new login. - Clear stale site data if the stored local mock session no longer matches current fixtures.
npx playwright installIf Edge is part of the selected projects, it must also be installed or the Edge project must be excluded during local runs.
Confirm the viewport, color scheme, operating system, fonts, and reduced-motion settings before accepting new baselines. Review every image difference; do not update snapshots merely to make the test pass.
Run npm run openapi:generate, inspect the contract notes under docs/api, and verify that the canonical YAML was not reformatted or changed without updating its approved checksum and operation lock.
Contributions should be made through focused branches and pull requests.
- Create a branch from the current integration branch.
- Keep changes scoped to one feature or concern.
- Add or update tests with the implementation.
- Run the full relevant quality suite.
- Document environment, contract, route, or workflow changes.
- Open a pull request with a concise description, verification evidence, and screenshots for visible UI changes.
Suggested commit format:
type(scope): short description
Examples:
feat(cv-builder): add record-level certificate selection
fix(shortlists): preserve page state after candidate removal
test(academic-ledger): cover invalid staged rows
docs(readme): document live backend testing
- Frontend folder structure
- Routing map
- State management notes
- Generated API metadata notes
- OpenAPI v1.6.0 validation report
- Contract traceability matrix
Some historical architecture and sprint reports are retained as delivery evidence. When they conflict with implementation, use the current route definitions, package scripts, canonical OpenAPI v1.6.0 contract, and source code as the authoritative references.
Copyright (c) 2026 University of Ruhuna, Department of Computer Science.
All rights reserved.
This software and associated documentation files (the "Software") are the proprietary property of the University of Ruhuna, Department of Computer Science. Unauthorized copying, distribution, modification, or use of this Software, in whole or in part, via any medium, is strictly prohibited without the prior written permission of the copyright holder.
This Software is developed as part of the CV Management and Deterministic Internship Candidate Filtering System project.