79 lines
4.5 KiB
Markdown
79 lines
4.5 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project
|
|
|
|
`aplp.frontend.react` — React frontend for APLP (Adaptive Personal Learning Platform), the learner-facing app (`aplp-web`). Thin client only: it calls the `aplp.backend.spring` REST API and holds no domain business rules (mastery/progress/adaptive decisions all come from the backend).
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
npm run dev # Vite dev server
|
|
npm run build # tsc -b (typecheck) + vite build
|
|
npm run typecheck # tsc -b --noEmit
|
|
npm run lint # oxlint
|
|
npm run lint:fix
|
|
npm run format # prettier --write .
|
|
npm run format:check
|
|
npm test # vitest run (single run)
|
|
npm run test:watch # vitest watch mode
|
|
npm run test:coverage
|
|
```
|
|
|
|
Run a single test file: `npx vitest run src/features/auth/store/authStore.test.ts` (or `npx vitest src/path/to/File.test.tsx` for watch mode on one file).
|
|
|
|
Backend must be running locally for the app to function against real APIs (default `VITE_API_BASE_URL=http://localhost:8080/api/v1`, see `.env.example`).
|
|
|
|
## Architecture
|
|
|
|
```
|
|
src/
|
|
├── app/ # entry, router (App.tsx), layouts, top-level pages, providers (QueryProvider)
|
|
├── api/ # axios client (src/api/client.ts), tokenStorage
|
|
├── features/ # vertical feature modules: auth (built), learner/course/learning/assessment/adaptive/... (planned per docs/PHASES.md)
|
|
│ └── <feature>/
|
|
│ ├── api/ # calls to backend endpoints for this feature
|
|
│ ├── components/
|
|
│ ├── hooks/
|
|
│ ├── pages/ # route-level views
|
|
│ ├── store/ # zustand store, if the feature needs one
|
|
│ └── types.ts
|
|
├── shared/ # shared components (src/shared/components), config (src/shared/config/env.ts)
|
|
└── types/ # cross-feature types / DTO contracts (src/types/api.ts)
|
|
```
|
|
|
|
Path alias `@/` → `src/` (configured in `vite.config.ts` and `tsconfig`).
|
|
|
|
### Data flow
|
|
|
|
UI component → hooks (React Query for server state, Zustand for cross-app client state, `useState` for local state) → `src/api` axios wrapper → backend REST API.
|
|
|
|
- Server state (fetched/cached data) always goes through TanStack Query — never duplicate it into a Zustand store.
|
|
- All backend calls go through `src/api`; don't call axios/fetch directly from components.
|
|
|
|
### Auth flow
|
|
|
|
- Access token: in-memory only (`src/api/tokenStorage.ts`), never persisted — XSS mitigation. Cleared on reload.
|
|
- Refresh token: currently stored in `localStorage` by `tokenStorage.ts` (note: this differs from `docs/ARCHITECTURE.md`, which documents the original design as an HttpOnly cookie managed entirely by the backend — treat the code as source of truth, not the doc, if the two disagree).
|
|
- The axios client (`src/api/client.ts`) auto-handles `401`s: on a non-auth-endpoint 401 it calls the registered `RefreshHandler` once (deduped via a shared `refreshPromise`), retries the original request with the new token, and calls `UnauthorizedHandler` (logout) if refresh fails. Auth endpoints (`/auth/*`) are excluded from this retry to avoid loops.
|
|
- `registerAuthHandlers()` wires the auth feature's refresh/logout logic into the generic api client — the api layer stays auth-feature-agnostic.
|
|
- Route protection via `ProtectedRoute` (`src/features/auth/components/ProtectedRoute.tsx`), wrapping routes in `App.tsx`.
|
|
- `useAuthStore.getState().init()` runs once on app mount (`App.tsx`) to hydrate auth state.
|
|
|
|
## Conventions (from docs/CONVENTIONS.md)
|
|
|
|
- TypeScript everywhere; avoid `any`. Props via `interface`.
|
|
- Naming: components PascalCase, hooks `useX` camelCase, API functions camelCase, types/interfaces PascalCase.
|
|
- Test files sit next to source: `Component.test.tsx`.
|
|
- React Query keys: array form, e.g. `['course', id]`.
|
|
- Every fetch/save view handles loading, empty, error, success states, using the shared components in `src/shared/components` (`Spinner`, `EmptyState`, `ErrorState`, `ErrorBoundary`).
|
|
- Errors surfaced to users must be friendly messages derived from the backend's `ApiError` shape (`src/types/api.ts`) — never raw stack traces.
|
|
|
|
## Docs
|
|
|
|
`docs/ARCHITECTURE.md`, `docs/CONVENTIONS.md`, `docs/SETUP.md`, `docs/PHASES.md` — the latter maps each upcoming feature phase (learner profile, course, learning, assessment, adaptive, recommendation, assistance, account) to frontend work; check it before scaffolding a new `features/<name>` module.
|
|
|
|
## Design
|
|
|
|
Alway using `docs/DESIGN.md` file to code everything relevant to style and UI |