181 行
8.4 KiB
Markdown
181 行
8.4 KiB
Markdown
# 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`:
|
|
|
|
```sh
|
|
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:
|
|
|
|
```sh
|
|
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.json` enables `strict`,
|
|
`noUnusedLocals`, `noUnusedParameters`, `erasableSyntaxOnly`,
|
|
`noFallthroughCasesInSwitch`, and `noUncheckedSideEffectImports`.
|
|
- Keep types explicit at module boundaries, API helpers, and exported utilities.
|
|
- Use `import type` for type-only imports.
|
|
- Prefer existing shared types from `src/types.ts` before 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-dom` route params and navigation patterns already present in `src/App.tsx`.
|
|
- Encode URL path-segment values with `encodeURIComponent`.
|
|
|
|
## TanStack Query
|
|
|
|
- Use `@tanstack/react-query` for 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 as
|
|
`posts.ts`, `tags.ts`, or `wiki.ts`.
|
|
- Use `useQueryClient().invalidateQueries` with the shared root keys when
|
|
mutations affect cached lists or detail views.
|
|
- The app-wide `QueryClient` is configured in `src/main.tsx`; do not create
|
|
additional clients in feature code.
|
|
|
|
## API calls
|
|
|
|
- Use `src/lib/api.ts` for HTTP calls.
|
|
- The API wrapper attaches `X-Transfer-Code` from `localStorage` and 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 to `frontend/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 `cn` from `src/lib/utils.ts` for conditional class names and class merging.
|
|
- Reuse components from `src/components/common`, `src/components/layout`, and
|
|
`src/components/ui` before 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.js` safelist
|
|
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.
|
|
- Treat TSX formatting rules as hard constraints, not preferences. Before
|
|
finishing a TSX edit, inspect the edited hunks for closing `)`, `]`, and `}`
|
|
placement and fix violations instead of relying on formatter defaults.
|
|
- For long Tailwind `className` strings, 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.
|
|
- In TypeScript and TSX function declarations, including `const` arrow
|
|
function declarations, when the parameter list spans multiple lines, always
|
|
put the closing parenthesis at the beginning of its own line before the return
|
|
type or `=>`. Do not put that closing `)` at the end of the previous line.
|
|
- Do not write React component declarations in the common Prettier form
|
|
`const Component = ({ ... }) => (` when the destructured parameter spans
|
|
multiple lines. Use the project form with the opening `(` after `=`, the
|
|
destructured object as the argument, and the closing parameter `)` on its own
|
|
line before `=>`.
|
|
- In TypeScript and TSX, never place a closing parenthesis at the beginning of
|
|
a line except for a multi-line function declaration parameter list.
|
|
- Never place a closing square bracket at the beginning of a line.
|
|
- For object literals, type literals, import/export named bindings, destructuring
|
|
patterns, and other associative-array-style braces, do not place the closing
|
|
brace at the beginning of a line. Keep `}` on the same line as the final
|
|
property, binding, or specifier unless that would violate the line limit.
|
|
Function, lambda, callback, and block closing braces are exempt and should
|
|
stay on their own line when that fits the local style. When a function,
|
|
lambda, callback, or block body spans multiple lines, do not put its closing
|
|
`}` at the end of the previous line.
|
|
- For arrays and tuple-like lists, do not place the closing `]` at the
|
|
beginning of a line. Keep `]` on the same line as the final element unless
|
|
that would violate the line limit.
|
|
- For function and method calls, do not place the closing `)` at the beginning
|
|
of a line. The only TypeScript/TSX exception is the closing parameter `)` of a
|
|
multi-line function declaration.
|
|
- Do not add braces around `if`, `else`, or `for` bodies when the body is a
|
|
single physical line.
|
|
- Always add braces around `if`, `else`, or `for` bodies 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`,
|
|
and `eslint-plugin-react-refresh`.
|
|
- The hooks rules are enforced; fix hook ordering instead of disabling the rule.
|
|
- `react-refresh/only-export-components` is enabled as a warning with `allowConstantExport`.
|
|
- 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.
|