6.3 KiB
6.3 KiB
AnthoLume Frontend Agent Guide
Read this file for work in frontend/.
Also follow the repository root guide at ../AGENTS.md.
1) Stack
- Package manager:
pnpm - Framework: React + Vite
- Data fetching: React Query
- API generation: Orval
- Styling: Tailwind CSS v4 (CSS-first config)
- Linting: oxlint (config in
.oxlintrc.json) +oxlint-tailwindcssfor Tailwind rules - Formatting: Prettier
2) Conventions
- Use local icon components from
src/icons/. - Do not add external icon libraries.
- Prefer generated types from
src/generated/model/overany. - Unwrap API responses by narrowing on
status(e.g.data?.status === 200 ? data.data : undefined); the generated response types are discriminated unions, so this needs noas XResponsecast. - Type form submit handlers as
SyntheticEvent(optionallySyntheticEvent<HTMLFormElement>);@types/react@19deprecatesFormEvent. - Route mutation success/error feedback through
useMutationWithToast(src/hooks/); error-toast-on-failure is the app-wide pattern (treat non-2xx as failure). - Shared input styling lives in
TextInput/ the exportedinputClassName(src/components/TextInput.tsx); reuse rather than re-pasting the input class string. - Render tabular data with the shared
<Table>(src/components/Table.tsx). Columns are{ id, header: ReactNode, render(row, index), className? }—idis decoupled from data, so action columns are first-class. The table owns its own loading skeleton and empty state; don't hand-roll<table>markup for data grids. (Genuinely different widget shapes — e.g. a file-browser or a card-grid — are fine to build bespoke.) - Nav items and page titles come from
src/components/navigation.ts(navItems,adminNavItems,getPageTitle) — add routes there, not inLayout/HamburgerMenu. - Avoid custom class names in JSX
classNamevalues unless the Tailwind lint config already allows them. - For decorative icons in inputs or labels, disable hover styling via the icon component API rather than overriding it ad hoc.
- Prefer
LoadingStatefor result-area loading indicators (the single loading convention); avoid early returns that unmount search/filter forms during fetches. - Use theme tokens defined in
src/index.css@theme(bg-surface,text-content,border-border,primary, etc.) for new UI work instead of adding raw light/dark color pairs. There is notailwind.config.js— Tailwind v4 config is CSS-first. - Semantic colors map to runtime CSS variables (
--color-x: rgb(var(--x))) via@theme inline; light/dark values live in:root/.darkinsrc/index.css. Dark mode is class-based via@custom-variant dark, toggled byThemeProvider. - Store frontend-only preferences in
src/utils/localSettings.tsso appearance and view settings share one local-storage shape.
3) Generated API client
- Do not edit
src/generated/**directly. - Edit
../api/v1/openapi.yamland regenerate instead. - Regenerate with:
pnpm run generate:api
Important behavior
- The generated client returns
{ data, status, headers }for both success and error responses. - Do not assume non-2xx responses throw.
- Trust the generated discriminated-union response types and narrow on
status; avoid hand-rolled re-validation of fields the schema already guarantees. - Centralize mutation/reqest error handling via
useMutationWithToast(toast options) orgetResponseError(utils/errors) for imperative flows — don't re-implement inlinestatuschecks or'message' in response.dataextraction.
4) Auth / Query State
- When changing auth flows, account for React Query cache state.
- Pay special attention to
/api/v1/auth/me. - A local auth state update may not be enough if cached query data still reflects a previous auth state.
5) Commands
- Lint:
pnpm run lint - Typecheck:
pnpm run typecheck - Lint fix:
pnpm run lint:fix - Format check:
pnpm run format - Format fix:
pnpm run format:fix - Build:
pnpm run build - Generate API client:
pnpm run generate:api
6) Validation Notes
- oxlint ignores
src/generated/**anddist/**(viaignorePatternsin.oxlintrc.json). lintrunsoxlint --max-warnings=0; keep the tree warning-free.react-hooks/exhaustive-depsis enforced — fix deps rather than disabling the rule; use a justified inline// oxlint-disable-next-lineonly for genuine init-once effects.- The Tailwind lint plugin uses oxlint
jsPlugins(experimental, not run by the editor language server), so Tailwind diagnostics surface via CLI/CI, not in-editor. It reads the theme fromsrc/index.css(settings.tailwindcss.entryPoint). - Frontend unit tests use Vitest and live alongside source as
src/**/*.test.ts(x). - Read
TESTING_STRATEGY.mdbefore adding or expanding frontend tests. - Prefer tests for meaningful app behavior, branching logic, side effects, and user-visible outcomes.
- Avoid low-value tests that mainly assert exact styling classes, duplicate existing coverage, or re-test framework/library behavior.
pnpm run lintincludes test files but does not typecheck.- Use
pnpm run typecheckto run TypeScript validation for app code and colocated tests without a full production build. - Run frontend tests with
pnpm run test. pnpm run buildstill runstsc && vite build, so unrelated TypeScript issues elsewhere insrc/can fail the build.- When possible, validate changed files directly before escalating to full-project fixes.
7) Live Dev Server Debugging
- Use
glimpseto inspect the running Vite dev server atlocalhost:5173:glimpse snapshot http://localhost:5173/some-page --wait-until=complete --timeout=15000 glimpse screenshot http://localhost:5173/some-page --wait-until=complete --output=_scratch/page.png glimpse exec http://localhost:5173/some-page --wait-until=complete --timeout=20000 --js='return document.title' - Use
curlfor API endpoint testing (bothlocalhost:5173via proxy andlocalhost:8585directly). - Do not monkey-patch
window.fetchinglimpse exec; Firefox rejects it. Test API calls withcurlinstead.
8) Updating This File
After completing a frontend task, update this file if you learned something general that would help future frontend agents.
Rules for updates:
- Add only frontend-wide guidance.
- Do not record one-off task history.
- Keep updates concise and action-oriented.
- Prefer notes that prevent repeated mistakes.