148 行
6.2 KiB
Markdown
148 行
6.2 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.
|
|
|
|
## 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.
|
|
- 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.
|
|
- 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.
|