All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 7s
- /home: כרטיס "מה ממתין להכרעתך" ב-aside (מצביע INV-IA1 ל-/approvals; usePendingApprovals, ללא מונה-מתחרה) — תואם מוקאפ 04-home המאושר. - web-ui/AGENTS.md: §"שער-עיצוב חובה — Claude Design קודם" — כל יצירת/שינוי עמוד-UI עוברת קודם דרך פרויקט Claude Design "עוזר משפטי — IA Redesign (X17)" (7a85b323-d880-4b6d-bac5-d4aa396fe93c) לאישור, ורק אז מוטמע (הנחיית חיים). בדיקה: npx tsc --noEmit ✓. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
262 lines
11 KiB
Markdown
262 lines
11 KiB
Markdown
<!-- BEGIN:nextjs-agent-rules -->
|
||
# This is NOT the Next.js you know
|
||
|
||
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
|
||
<!-- END:nextjs-agent-rules -->
|
||
|
||
---
|
||
|
||
## ⚠️ שער-עיצוב חובה — Claude Design קודם (הנחיית חיים, 2026-06-11)
|
||
|
||
**כל יצירת עמוד/דף חדש, וכל שינוי-UI בעמוד/דף קיים — מכל סיבה — חייב לעבור קודם דרך Claude Design לאישור, ורק לאחר אישור מטמיעים בקוד.** אין לשנות/ליצור עמוד-UI ישירות בלי מעבר דרך השער.
|
||
|
||
**הפרויקט הקנוני (כל הדפים נמצאים שם):**
|
||
- שם: **`עוזר משפטי — IA Redesign (X17)`** ב-[claude.ai/design](https://claude.ai/design).
|
||
- מזהה-פרויקט: `7a85b323-d880-4b6d-bac5-d4aa396fe93c`.
|
||
- גישה: כלי `DesignSync` (claude.ai/design). מכיל את כל 17 הדפים כ-preview-cards תחת קבוצה `IA Redesign (X17)`, בנויים מטוקני-העיצוב האמיתיים (`globals.css`: navy `#0f172a`, gold `#a97d3a`, cream `#f5f1e8`, parchment, rule…), Heebo, RTL.
|
||
|
||
**הפרוטוקול לכל בקשת-עמוד/שינוי-UI:**
|
||
1. **בקשת-עיצוב ל-Claude Design** — לבנות/לעדכן את ה-preview של העמוד בפרויקט הזה (HTML self-contained, `<!-- @dsCard group="IA Redesign (X17)" -->` כשורה ראשונה, טוקנים+Heebo+RTL זהים), `write_files` + `register_assets` דרך `DesignSync`.
|
||
2. **להציג לחיים לאישור** — ולהמתין לאישור מפורש.
|
||
3. **רק אחרי אישור** — להטמיע בקוד (Next 16 + Tailwind v4 + shadcn), לשמר hooks/לוגיקה, tsc/lint, worktree + PR.
|
||
|
||
חריג יחיד: תיקון-באג שאינו משנה את ה-UI הוויזואלי (לוגיקה/נתון/hook בלבד) — לא דורש מעבר דרך השער. בכל ספק — דרך השער.
|
||
|
||
> רקע: יוזמת ה-IA (X17, #127/#130–132) → מוקאפי-Claude-Design ל-17 הדפים (מאושרים) → תרגום לפרודקשן. ראה memory `feedback_claude_design_gate` ו-`project_ia_redesign_waves`.
|
||
|
||
---
|
||
|
||
## Stack
|
||
|
||
| Layer | Technology | Version |
|
||
|-------|-----------|---------|
|
||
| Framework | Next.js | 16.2.3 |
|
||
| UI | React | 19.2.4 |
|
||
| Styles | Tailwind CSS | v4 |
|
||
| Components | shadcn/ui | latest via `shadcn` CLI |
|
||
| Data fetching | TanStack Query | v5 |
|
||
| Forms | react-hook-form + zod | v7 / v4 |
|
||
| Language | TypeScript | 5 |
|
||
| Direction | Hebrew RTL | `dir="rtl"` throughout |
|
||
|
||
---
|
||
|
||
## Commands
|
||
|
||
```bash
|
||
# Regenerate API types from the live FastAPI schema — RUN AFTER EVERY BACKEND CHANGE
|
||
npm run api:types
|
||
|
||
# Validate before every push
|
||
npm run lint
|
||
npm run build
|
||
|
||
# Local dev (rare — prod runs inside Docker; no local Python env exists)
|
||
npm run dev # requires NEXT_PUBLIC_API_ORIGIN=http://127.0.0.1:8000 or similar
|
||
```
|
||
|
||
**`npm run api:types` is mandatory** any time a FastAPI endpoint is added, removed, or its request/response shape changes. It fetches `https://legal-ai.nautilus.marcusgroup.org/openapi.json` and writes `src/lib/api/types.ts`.
|
||
|
||
---
|
||
|
||
## Backend Proxy — `/api/*`
|
||
|
||
`next.config.ts` transparently rewrites all `/api/*` requests to the FastAPI backend:
|
||
|
||
- In Docker (production): `http://127.0.0.1:8000`
|
||
- Override via env var: `NEXT_PUBLIC_API_ORIGIN`
|
||
|
||
**Never hardcode the backend origin in component code.** Always use relative paths like `/api/cases`.
|
||
|
||
The typed fetch wrapper lives in `src/lib/api/client.ts` — use `apiRequest<T>(path, options)`. It throws `ApiError` on non-2xx responses with the parsed body and status code.
|
||
|
||
---
|
||
|
||
## API Types — Never Edit by Hand
|
||
|
||
`src/lib/api/types.ts` is **auto-generated** by `openapi-typescript` from the live FastAPI OpenAPI schema.
|
||
|
||
- **Do NOT edit `src/lib/api/types.ts` manually** — changes will be overwritten on the next `npm run api:types` run.
|
||
- The typed helper modules in `src/lib/api/` (e.g. `cases.ts`, `documents.ts`, `precedents.ts`) ARE hand-written and import from `types.ts`. These are safe to edit.
|
||
- When adding a new API domain, create a new typed module in `src/lib/api/<domain>.ts` following the existing pattern.
|
||
|
||
---
|
||
|
||
## Tailwind CSS v4 — Breaking Changes from v3
|
||
|
||
Tailwind v4 has a completely different configuration model.
|
||
|
||
**What does NOT exist in v4:**
|
||
- `tailwind.config.ts` / `tailwind.config.js` — there is no config file
|
||
- `@tailwind base;` / `@tailwind components;` / `@tailwind utilities;` directives
|
||
- `tailwind.config.theme.extend` object
|
||
|
||
**What v4 uses instead:**
|
||
```css
|
||
/* globals.css — already set up, do not change */
|
||
@import "tailwindcss";
|
||
@import "tw-animate-css";
|
||
@import "shadcn/tailwind.css";
|
||
|
||
@theme {
|
||
/* Design tokens defined here as CSS custom properties */
|
||
--color-navy: #0f172a;
|
||
/* ... */
|
||
}
|
||
```
|
||
|
||
- Custom tokens go inside `@theme {}` in `globals.css`.
|
||
- Custom variants use `@custom-variant`.
|
||
- Class names are the same (e.g. `bg-navy`, `text-gold`), but the config source is CSS, not JS.
|
||
- PostCSS is configured via `@tailwindcss/postcss` (devDependency).
|
||
|
||
---
|
||
|
||
## shadcn/ui Components
|
||
|
||
Adding a new component:
|
||
```bash
|
||
npx shadcn add <component-name>
|
||
# e.g. npx shadcn add table
|
||
```
|
||
|
||
Installed components live in `src/components/ui/`. They are editable (shadcn copies the source, not a package import). The `radix-ui` package (v1.4) is the underlying primitive.
|
||
|
||
- Do NOT `npm install @radix-ui/react-*` directly — use `npx shadcn add` which installs the correct Radix version and generates the shadcn wrapper.
|
||
- Design tokens in `globals.css` (`--color-navy`, `--color-gold`, etc.) are already mapped to the shadcn semantic tokens (`background`, `foreground`, `primary`, etc.), so shadcn components inherit the editorial/judicial aesthetic automatically.
|
||
|
||
---
|
||
|
||
## TanStack Query v5
|
||
|
||
**v5 has breaking API changes from v4.** Key patterns used in this codebase:
|
||
|
||
```typescript
|
||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||
|
||
// Reading data
|
||
const { data, isLoading, isError } = useQuery({
|
||
queryKey: ["cases"],
|
||
queryFn: () => apiRequest<CaseListResponse>("/api/cases"),
|
||
});
|
||
|
||
// Writing data
|
||
const queryClient = useQueryClient();
|
||
const mutation = useMutation({
|
||
mutationFn: (body: CreateCaseRequest) =>
|
||
apiRequest<Case>("/api/cases", { method: "POST", body }),
|
||
onSuccess: () => {
|
||
queryClient.invalidateQueries({ queryKey: ["cases"] });
|
||
},
|
||
});
|
||
```
|
||
|
||
**v5 changes from v4:**
|
||
- `useQuery` no longer accepts positional arguments — always use the options object.
|
||
- `isLoading` is replaced by `isPending` for mutations (but `isLoading` still works for queries).
|
||
- `onSuccess`/`onError`/`onSettled` callbacks on `useQuery` are removed — use mutation callbacks or `useEffect` instead.
|
||
- `getQueryData` / `setQueryData` are unchanged.
|
||
|
||
The shared `QueryClient` is created in `src/lib/api/client.ts` via `makeQueryClient()` and provided by `src/lib/providers.tsx`.
|
||
|
||
---
|
||
|
||
## RTL — Hebrew UI Rules
|
||
|
||
**All UI is Hebrew, right-to-left.** The `<html>` element has `dir="rtl"` and `lang="he"`.
|
||
|
||
Use **logical CSS properties** instead of directional ones:
|
||
|
||
| Avoid (directional) | Use (logical) |
|
||
|---------------------|--------------|
|
||
| `ml-*` / `mr-*` | `ms-*` (start) / `me-*` (end) |
|
||
| `pl-*` / `pr-*` | `ps-*` (start) / `pe-*` (end) |
|
||
| `text-left` | `text-start` |
|
||
| `text-right` | `text-end` |
|
||
| `float-left` | `float-start` |
|
||
| `border-l-*` | `border-s-*` |
|
||
|
||
In RTL, "start" = right side, "end" = left side. Using logical properties means the layout works automatically without RTL overrides.
|
||
|
||
Flexbox direction: `flex-row` in RTL naturally flows right-to-left. Use `flex-row-reverse` only when you need LTR inside an RTL context.
|
||
|
||
---
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
src/
|
||
├── app/ # Next.js App Router pages
|
||
│ ├── layout.tsx # Root layout — sets dir="rtl", applies fonts
|
||
│ ├── globals.css # Tailwind v4 imports + design tokens + :root vars
|
||
│ ├── cases/ # Case management pages
|
||
│ ├── precedents/ # Precedent library pages
|
||
│ ├── methodology/ # Methodology browser
|
||
│ ├── training/ # Training document management
|
||
│ ├── settings/ # Application settings
|
||
│ └── skills/ # Skills management
|
||
├── components/
|
||
│ ├── ui/ # shadcn primitives (editable copies)
|
||
│ ├── app-shell.tsx # Top-level shell with nav
|
||
│ ├── cases/ # Case-domain components
|
||
│ ├── documents/ # Document viewer components
|
||
│ ├── precedents/ # Precedent components
|
||
│ └── compose/ # Decision drafting / block editor
|
||
├── lib/
|
||
│ ├── api/
|
||
│ │ ├── types.ts # AUTO-GENERATED — never edit
|
||
│ │ ├── client.ts # apiRequest<T> + QueryClient factory
|
||
│ │ ├── cases.ts # Typed case API helpers
|
||
│ │ ├── documents.ts # Typed document API helpers
|
||
│ │ └── ... # One file per API domain
|
||
│ ├── providers.tsx # TanStack Query + theme providers
|
||
│ ├── utils.ts # cn() and other shared utilities
|
||
│ ├── doc-types.ts # Document type constants
|
||
│ └── sse.ts # Server-Sent Events helper for streaming
|
||
```
|
||
|
||
---
|
||
|
||
## Forms
|
||
|
||
Forms use **react-hook-form** (v7) with **zod** (v4) validation via `@hookform/resolvers`:
|
||
|
||
```typescript
|
||
import { useForm } from "react-hook-form";
|
||
import { zodResolver } from "@hookform/resolvers/zod";
|
||
import { z } from "zod";
|
||
|
||
const schema = z.object({ title: z.string().min(1) });
|
||
type FormValues = z.infer<typeof schema>;
|
||
|
||
const form = useForm<FormValues>({ resolver: zodResolver(schema) });
|
||
```
|
||
|
||
---
|
||
|
||
## Notifications / Toasts
|
||
|
||
Use **sonner** (`import { toast } from "sonner"`). The `<Toaster>` is mounted in `src/lib/providers.tsx`.
|
||
|
||
```typescript
|
||
toast.success("התיק נשמר בהצלחה");
|
||
toast.error("שגיאה בשמירה");
|
||
```
|
||
|
||
---
|
||
|
||
## Streaming (SSE)
|
||
|
||
Server-sent events are used for long-running AI operations (drafting, analysis). The helper is in `src/lib/sse.ts`. Use it instead of raw `EventSource`.
|
||
|
||
---
|
||
|
||
## Deploy
|
||
|
||
This frontend runs **inside Docker via Coolify** — not as a standalone Node process.
|
||
|
||
- **No `npm run dev` on the server** — there is no local Python environment for the backend.
|
||
- To see changes in production: `git commit` + `git push origin main` → Gitea Actions builds image → Coolify redeploys (~2-4 min).
|
||
- Prod URL: `https://legal-ai.nautilus.marcusgroup.org`
|
||
- The Next.js output is `standalone` (see `next.config.ts: output: "standalone"`).
|