- /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>
11 KiB
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.
⚠️ שער-עיצוב חובה — Claude Design קודם (הנחיית חיים, 2026-06-11)
כל יצירת עמוד/דף חדש, וכל שינוי-UI בעמוד/דף קיים — מכל סיבה — חייב לעבור קודם דרך Claude Design לאישור, ורק לאחר אישור מטמיעים בקוד. אין לשנות/ליצור עמוד-UI ישירות בלי מעבר דרך השער.
הפרויקט הקנוני (כל הדפים נמצאים שם):
- שם:
עוזר משפטי — IA Redesign (X17)ב-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:
- בקשת-עיצוב ל-Claude Design — לבנות/לעדכן את ה-preview של העמוד בפרויקט הזה (HTML self-contained,
<!-- @dsCard group="IA Redesign (X17)" -->כשורה ראשונה, טוקנים+Heebo+RTL זהים),write_files+register_assetsדרךDesignSync. - להציג לחיים לאישור — ולהמתין לאישור מפורש.
- רק אחרי אישור — להטמיע בקוד (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
# 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.tsmanually — changes will be overwritten on the nextnpm run api:typesrun. - The typed helper modules in
src/lib/api/(e.g.cases.ts,documents.ts,precedents.ts) ARE hand-written and import fromtypes.ts. These are safe to edit. - When adding a new API domain, create a new typed module in
src/lib/api/<domain>.tsfollowing 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;directivestailwind.config.theme.extendobject
What v4 uses instead:
/* 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 {}inglobals.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:
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 — usenpx shadcn addwhich 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:
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:
useQueryno longer accepts positional arguments — always use the options object.isLoadingis replaced byisPendingfor mutations (butisLoadingstill works for queries).onSuccess/onError/onSettledcallbacks onuseQueryare removed — use mutation callbacks oruseEffectinstead.getQueryData/setQueryDataare 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:
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.
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 devon 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(seenext.config.ts: output: "standalone").