Frontend / Dashboard¶
dashboard/ is a React 18 + TypeScript + Vite single-page application
using the Ant Design component library. State management is handled
with Redux Toolkit.
Directory layout (dashboard/src/)¶
| Directory | Contents |
|---|---|
routes/ |
browserRouter.tsx (React Router setup, lazy-loaded pages), web.tsx (page paths), api.tsx (backend endpoint URLs), requireAuth.tsx / requirePermission.tsx (route guard components) |
store/ |
The Redux Toolkit store (store/index.tsx) and slices (store/slices/adminSlice.tsx) |
services/ |
HTTP clients that talk to the backend: authApi.ts, dictionaryApi.ts, peopleApi.ts |
components/ |
Feature-scoped UI: auth/, dictionary/, layout/, loader/, settings/, theme/, users/ |
interfaces/ |
TypeScript type definitions (interfaces/models/) |
constants/ |
Constants |
utils/ |
Helper functions, API_BASE_URL resolution logic |
Route protection model¶
requireAuth.tsx validates the token against the backend's
GET /api/v1/auth/me endpoint before a page is rendered (the
"protected page flash" safeguard — while validation is pending, neither
protected content nor the login page is shown, only a loader).
requirePermission.tsx then applies page/action-level authorization
using the same PermissionKey contract as the backend
(dictionary.*/users.*/settings.* — see
Backend API and
dashboard/src/utils/permissions.ts, which must stay in sync with
backend middleware/auth.ts).
Theme (light/dark)¶
components/theme/AppTheme.tsx is the application's own light/dark
theme provider — it works by swapping Ant Design ConfigProvider theme
tokens. (This is separate from this documentation site's own Material
theme toggle — see Home; they are two independent systems,
one for the application's own UI, one for this docs site.)
API base URL logic¶
dashboard/src/utils/index.tsx:
- Development (
import.meta.env.DEV): always empty/relative — requests go to/api/v1/...on the same origin, and Vite's own/apiproxy (vite.config.ts) forwards them to the real backend.VITE_API_BASE_URLis intentionally ignored in dev. - Production build:
VITE_API_BASE_URL(a build-time env var — see the--build-argindashboard/Dockerfile.prodand the root.env.example) is used; the client is no longer behind a dev-server proxy and calls the backend's real address directly.
Testing¶
Component/unit tests are written with Vitest + React Testing Library +
jsdom under src/**/*.test.{ts,tsx} — see
Testing for details and known coverage gaps.
Development commands¶
cd dashboard
pnpm install --frozen-lockfile
pnpm run dev # hot-reload dev server (Vite)
pnpm run typecheck # tsc
pnpm run lint # ESLint
pnpm run build # production build (tsc && vite build)
pnpm test # Vitest
The package manager is strictly pnpm (dashboard/pnpm-lock.yaml is
the source of truth) — never mix it with npm/yarn, see
Git & CI/CD.