gendesign/.claude/rules/frontend.md

66 lines
3.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
paths:
- frontend/**/*.{ts,tsx,jsx,js}
- tradein-mvp/frontend/**/*.{ts,tsx,jsx,js}
---
# Frontend conventions — Next.js 15 / React 19 / TypeScript 5
## Critical
- **App router only** — НЕ `pages/` router
- **TanStack Query** для data-fetching — никакого `useEffect` для HTTP запросов
- **TS strict** — никаких `any`; для unknown shape → `unknown` + narrow
- TanStack Query keys — массивы: `["scrape-logs", scraperType, runIdFilter]`
- Tailwind 4 утилитарные классы; inline styles только для динамических значений
- Server / Client components разделены явно — `"use client"` в начале client'а
## XSS prevention (recurring bug class)
При рендере markdown / user-supplied content:
- **URL validation**: allowlist schemes перед инъекцией в `href=` / `src=`:
-`https://`, `http://`, `/`, `#`, `mailto:`
-`javascript:`, `data:`, `vbscript:`, `file:` → fallback `#`
- Pattern: helper `safeUrl(url: string): string` перед записью в attr
Reference: vault `Bug_RenderMarkdown_JavascriptUrl_May14` (`renderMarkdown.ts:safeUrl`).
## After backend schema change
```
cd frontend && npm run codegen
```
Обновляет `src/lib/api-types.ts` из live OpenAPI (`npm run codegen` = `openapi-typescript … -o src/lib/api-types.ts`). Без этого frontend build упадёт на missing types.
## package.json + lockfile sync (CRITICAL — deploy aborts on mismatch)
Если меняешь `frontend/package.json` (add/remove/bump dep) — **обязан** также:
```bash
cd frontend && npm install --legacy-peer-deps --no-audit --no-fund
```
И закоммитить обновлённый `frontend/package-lock.json` в той же ветке.
**Why:** `frontend/Dockerfile` использует `npm ci --legacy-peer-deps` — этот режим **требует** точного match между `package.json` и `package-lock.json`. Mismatch → `npm error Missing: <pkg>@<version> from lock file` → builder fails → `docker compose --abort-on-container-exit`**весь deploy aborts** (frontend + backend rollback).
- Pre-push check: `git diff main..HEAD -- frontend/package.json frontend/package-lock.json` — если только один из двух тронут → STOP, regen lock.
- Imports без deps entry (TypeScript авто-resolve через transitive) — **latent bomb** до first `npm ci`.
- Reference incident: PR #344 (2026-05-17) добавил `lucide-react` без regen lockfile → deploy #135 fail → P0 hotfix PR #345 (commit `6ee20294f2`).
## Prettier / lint
- 2 spaces, trailing comma, double quotes (config)
- `prettier` hook auto-rewrites файл → нужен повторный `git add`
- ESLint в pre-commit: no unused imports, no console.log, exhaustive deps
## Запреты
-`any` в TypeScript — `unknown` + type guard
-`useEffect` для HTTP — TanStack Query
-`pages/` router — только `app/`
-`console.log` в prod-коде
- ❌ Inline в `href`/`src` без validation (XSS vector)
- ❌ Hardcoded URLs — `process.env.NEXT_PUBLIC_API_URL`