4.3 KiB
4.3 KiB
frontend/AGENTS.md
Scope
These rules apply to work under frontend/.
This is a Vite + React + TypeScript app using TanStack Query, Tailwind CSS, Framer Motion, Radix UI-style components, MDX, and Zustand.
Commands
Use only scripts that exist in package.json:
npm run dev
npm run build
npm run lint
npm run preview
npm run build runs tsc -b && vite build, and postbuild runs node scripts/generate-sitemap.js.
There is currently no test script in package.json. Do not run or report npm test unless a test script is added.
After frontend changes, run:
npm run build
npm run lint
If either command cannot be run or fails, report the exact command and failure.
TypeScript
- TypeScript is strict.
tsconfig.app.jsonenablesstrict,noUnusedLocals,noUnusedParameters,erasableSyntaxOnly,noFallthroughCasesInSwitch, andnoUncheckedSideEffectImports. - Keep types explicit at module boundaries, API helpers, and exported utilities.
- Use
import typefor type-only imports. - Prefer existing shared types from
src/types.tsbefore adding local duplicate types. - Preserve the repository's existing spacing style in TypeScript, including GNU-style spacing before call parentheses where it is already used.
- Prefer single quotes for strings unless interpolation or escaping makes double quotes better.
React
- Use function components.
- Existing page components commonly export an anonymous function satisfying
FC; match nearby file style when editing. - React hooks must be called unconditionally and at the top level of components or custom hooks.
- Keep page-level components under
src/pages. - Keep shared and feature components under
src/components. - Use
react-router-domroute params and navigation patterns already present insrc/App.tsx. - Encode URL path-segment values with
encodeURIComponent.
TanStack Query
- Use
@tanstack/react-queryfor server state. - Query keys should come from
src/lib/queryKeys.ts; add key builders there instead of using ad hoc arrays in components. - Fetch functions should live in domain helpers under
src/lib, such asposts.ts,tags.ts, orwiki.ts. - Use
useQueryClient().invalidateQuerieswith the shared root keys when mutations affect cached lists or detail views. - The app-wide
QueryClientis configured insrc/main.tsx; do not create additional clients in feature code.
API calls
- Use
src/lib/api.tsfor HTTP calls. - The API wrapper attaches
X-Transfer-CodefromlocalStorageand converts non-blob responses to camelCase. - Send Rails snake_case params and request body keys where the backend expects them.
- Do not bypass the API wrapper unless there is a specific reason, such as a third-party request outside the Rails API.
- For blob responses, pass
responseType: 'blob'so the wrapper does not camelCase the body.
Imports and aliases
- The
@alias points tofrontend/src. - Prefer
@/...imports for app code instead of long relative paths. - Keep type imports separate with
import type. - Match existing import grouping: external packages, app modules, then type imports.
Tailwind and UI
- Tailwind scans
src/**/*.{html,js,ts,jsx,tsx,mdx}. - Use
cnfromsrc/lib/utils.tsfor conditional class names and class merging. - Reuse components from
src/components/common,src/components/layout, andsrc/components/uibefore adding new primitives. - Keep Tailwind classes consistent with nearby components.
- When adding dynamic tag color classes, update
tailwind.config.jssafelist if the class cannot be statically detected. - Do not introduce new UI libraries or production dependencies without approval.
Lint and build constraints
- ESLint uses
@eslint/js,typescript-eslint,eslint-plugin-react-hooks, andeslint-plugin-react-refresh. - The hooks rules are enforced; fix hook ordering instead of disabling the rule.
react-refresh/only-export-componentsis enabled as a warning withallowConstantExport.- Build failures from unused locals or unused parameters are TypeScript errors, not lint-only issues.
Files to avoid in routine work
- Do not edit
dist/output directly. - Do not inspect or modify
node_modules/unless explicitly needed. - Keep generated build artifacts out of source changes unless the user asks for them.