6.4 KiB
6.4 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.
Do not create, modify, or run tests unless the user explicitly asks for test work. When the user asks for tests, keep working and rerun them until they pass or the remaining failure is clearly blocked.
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.
- Never write a TypeScript or TSX line longer than 99 characters.
- Aim to keep TypeScript and TSX lines within 79 characters where practical.
- Use 4-space logical indentation in TypeScript and TSX.
- For arrays, never put whitespace or a line break immediately before
]. - Keep the first element on the same line as
[by default. - If an array would exceed the line limit, break after
[and indent elements by 4 spaces. - In TypeScript and TSX only, replace every leading run of 8 spaces with a tab to reduce bytes.
- Treat one leading tab as exactly equivalent to 8 leading spaces.
- Use tabs only for leading indentation. Never replace spaces that occur after a non-space character on the same line.
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.
- Gate editing and other privileged controls with shared permission helpers
such as
canEditContent, instead of showing controls and relying only on a later API failure. - 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.
- Prefer restrained, content-first UI chrome: avoid adding card backgrounds, heavy borders, or nested panel decoration unless the surrounding screen already uses them.
- Keep operational screens dense and direct; trim explanatory copy and use short Japanese labels that fit the control.
- Preserve existing Japanese tone and orthography in nearby UI text, including old-kana wording where the file already uses it.
- 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.
TSX formatting
- Preserve compact TSX expression shapes such as inline ternary branches and
closing
</div>)forms when nearby code uses them. - For long Tailwind
classNamestrings, wrap across lines only when needed. - Keep continuation indentation aligned with the 4-space logical indentation rule, using tabs only as leading 8-space compression.
- Do not add braces around
if,else, orforbodies when the body is a single physical line. - Always add braces around
if,else, orforbodies when the body spans two or more physical lines, even if it is one statement. - Avoid reformatting unrelated JSX.
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.