Files
familienarchiv/frontend/CLAUDE.md
Marcel 86c13a230c docs(legibility): migrate CLAUDE.md rules into human docs — DOC-7
Processes all 7 CLAUDE.md files according to the 3-bucket classification.
Migration targets (CONTRIBUTING.md, docs/ARCHITECTURE.md, docs/DEPLOYMENT.md,
domain READMEs) are introduced by DOC-2/4/5/6 — this PR must merge last.

### scripts/CLAUDE.md → scripts/README.md
New `scripts/README.md` with full script documentation (preserving the
⚠️ destructive-operation warning on reset-db.sh). `scripts/CLAUDE.md`
reduced to a pointer + "document new scripts in README.md" reminder.

### .devcontainer/CLAUDE.md → .devcontainer/README.md
New `.devcontainer/README.md` with all configuration, usage, and limitations.
`devcontainer/CLAUDE.md` reduced to a single pointer line.

### docs/CLAUDE.md → docs/README.md
New `docs/README.md` covering the folder structure, ADR guide, infrastructure
docs, and specs folder. `docs/CLAUDE.md` reduced to pointer + ADR reminder.

### ocr-service/CLAUDE.md
Reduced to pointer to `ocr-service/README.md` (content migrated in DOC-6).
Kept LLM reminders: single-node constraint, ALLOWED_PDF_HOSTS SSRF risk.

### backend/CLAUDE.md
- Layering Rules → pointer to docs/ARCHITECTURE.md
- Error Handling → pointer to CONTRIBUTING.md + reminder
- Security/Permissions → pointer to docs/ARCHITECTURE.md + reminder
- Package Structure → tagged TODO post-REFACTOR-1
- Fixed errors.ts path to frontend/src/lib/shared/errors.ts
- Added ANNOTATE_ALL + BLOG_WRITE to permission list
- Key Entities, Entity Code Style, Services → kept (Bucket-2)

### root CLAUDE.md
- Stack, Infrastructure, Dev Container → pointers
- Layering Rules, Error Handling, Security, OpenAPI, API Client,
  Date Handling, UI Components, Frontend Error Handling → pointers + reminders
- Package Structure → tagged TODO post-REFACTOR-1
- Domain Model, Entity Code Style, Form Actions, Styling → kept (Bucket-2)

### frontend/CLAUDE.md
- API Client Pattern, Date Handling → pointers + reminders
- Key UI Components → pointer to domain READMEs
- Styling, Form Actions, How to Run, Vite Proxy, i18n → kept (Bucket-2)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 07:41:02 +02:00

7.9 KiB

Frontend — Familienarchiv

Overview

SvelteKit 2 application providing the Familienarchiv web UI. Server-side rendered (SSR) where beneficial, with client-side interactivity for document viewing, transcription, annotation, and admin workflows.

Tech Stack

  • Framework: SvelteKit 2 with Svelte 5 (runes mode)
  • Language: TypeScript 5.9
  • Styling: Tailwind CSS 4.1 + custom brand utilities
  • Build Tool: Vite 7
  • Adapter: @sveltejs/adapter-node (Node.js server, not static)
  • i18n: Paraglide.js 2.5 (@inlang/paraglide-js) — German (default), English, Spanish
  • API Client: openapi-fetch + openapi-typescript (generated from backend OpenAPI spec)
  • PDF Rendering: pdfjs-dist (PDF.js)
  • Testing:
    • Unit/Server: Vitest 4 (Node environment)
    • Component: Vitest Browser Mode with Playwright (Chromium)
    • E2E: Playwright (frontend/e2e/)

Project Structure

src/
├── routes/              # SvelteKit file-based routing
│   ├── +layout.svelte   # Global layout: header, nav, auth state
│   ├── +layout.server.ts # Loads current user, injects auth cookie
│   ├── +page.svelte     # Home / document search dashboard
│   ├── documents/       # Document CRUD, detail, edit, upload
│   ├── persons/         # Person directory, detail, edit, merge
│   ├── briefwechsel/    # Bilateral conversation timeline
│   ├── chronik/         # Unified activity feed
│   ├── admin/           # User, group, tag, OCR, system management
│   ├── api/             # Internal API proxies (server-side only)
│   ├── login/ logout/   # Auth pages
│   └── ...
├── lib/                 # Domain-based package structure (mirrors backend)
│   ├── document/        # Document domain: components, stores, services, utils
│   │   ├── annotation/  # Annotation overlay components
│   │   ├── comment/     # Comment thread components
│   │   └── transcription/ # Transcription editor + block logic
│   ├── person/          # Person domain: chips, typeahead, avatar, format
│   │   ├── relationship/ # Relationship form + chip components
│   │   └── genealogy/   # Stammbaum (family tree) components
│   ├── tag/             # Tag domain: TagInput, TagChipList, TagParentPicker
│   ├── geschichte/      # Geschichte (story) domain: editor + card
│   ├── notification/    # Notification bell + dropdown + store
│   ├── activity/        # Activity feed (Chronik) components
│   ├── conversation/    # Bilateral conversation (Briefwechsel) components
│   ├── ocr/             # OCR progress, training cards, trigger
│   ├── user/            # User profile/password/groups section components
│   ├── shared/          # Cross-domain utilities and primitives
│   │   ├── actions/     # Svelte actions (clickOutside, etc.)
│   │   ├── hooks/       # Reusable Svelte state hooks (useTypeahead, etc.)
│   │   ├── server/      # Server-only utilities (locale, session)
│   │   ├── services/    # Client-side service helpers
│   │   ├── utils/       # Pure utility functions (date, search, etc.)
│   │   ├── primitives/  # Generic UI primitives (BackButton, ProgressRing, etc.)
│   │   ├── dashboard/   # Dashboard stat components
│   │   ├── discussion/  # CommentThread + shared discussion UI
│   │   ├── help/        # Help/FAQ page components
│   │   ├── api.server.ts # Typed API client factory
│   │   ├── errors.ts    # Error code mapping (mirrors backend ErrorCode)
│   │   ├── types.ts     # Shared TypeScript types
│   │   ├── relativeTime.ts # Relative time formatting
│   │   └── utils.ts     # Top-level shared utilities
│   ├── generated/       # Auto-generated API types (openapi-typescript)
│   └── paraglide/       # Generated i18n code
├── hooks/               # SvelteKit hooks (handle, handleFetch)
└── ...                  # Other SvelteKit config files

For per-domain component inventories, see the domain READMEs in src/lib/<domain>/README.md.

API Client Pattern

→ See CONTRIBUTING.md §Frontend API client

LLM reminder: check !result.response.ok (not result.error — breaks when spec has no error responses); cast errors as result.error as unknown as { code?: string }; use result.data! after an ok check. For multipart/form-data (file uploads), bypass the typed client and use raw fetch.

Form Actions Pattern

// +page.server.ts
export const actions = {
	default: async ({ request, fetch }) => {
		const formData = await request.formData();
		const name = formData.get('name') as string; // cast needed — FormData returns FormDataEntryValue
		// ...
		return fail(400, { error: 'message' }); // on error
		throw redirect(303, '/target'); // on success
	}
};

Date Handling

→ See CONTRIBUTING.md §Date handling

LLM reminder: always append T12:00:00 when constructing new Date() from an ISO date string — prevents UTC timezone off-by-one errors. Forms use German dd.mm.yyyy format via handleDateInput() with a hidden ISO input.

Styling Conventions (Tailwind CSS 4)

Brand color utilities (defined in layout.css):

Class Value Usage
brand-navy #002850 Primary text, buttons, headers
brand-mint #A6DAD8 Accents, hover underlines, icons
brand-sand #E4E2D7 Page background, card borders

Typography:

  • font-serif (Merriweather) — body text, document titles, names
  • font-sans (Montserrat) — labels, metadata, UI chrome

Card pattern for content sections:

<div class="bg-white shadow-sm border border-brand-sand rounded-sm p-6">
    <h2 class="text-xs font-bold uppercase tracking-widest text-gray-400 mb-5">Section</h2>
    <!-- content -->
</div>

Key UI Components

→ See per-domain READMEs: src/lib/person/README.md, src/lib/tag/README.md, src/lib/document/README.md, src/lib/shared/README.md

LLM reminder: BackButton is at $lib/shared/primitives/BackButton.svelte — use it for all back navigation; never a static <a href>. API client is at $lib/shared/api.server.

How to Run

Development

cd frontend
npm install
npm run dev         # Dev server on port 5173 (or 3000 if --port 3000)

Build & Preview

npm run build       # Production build
npm run preview     # Preview production build

Code Quality

npm run lint        # Prettier + ESLint check
npm run format      # Auto-fix formatting
npm run check       # svelte-check (type checking)

Testing

npm run test              # Vitest unit + server tests (headless)
npm run test:coverage     # Coverage report (server project only)
npm run test:e2e          # Playwright E2E tests
npm run test:e2e:headed   # Playwright E2E with visible browser
npm run test:e2e:ui       # Playwright UI mode

Regenerate API Types

Requires backend running with --spring.profiles.active=dev:

npm run generate:api

Vite Proxy

During development, /api calls are proxied to the Spring Boot backend. The proxy injects the Authorization header from the auth_token cookie automatically (see vite.config.ts).

i18n (Paraglide)

Translations live in messages/{de,en,es}.json. The compiler generates type-safe helpers in src/lib/paraglide/. Run compilation manually with:

npx @inlang/paraglide-js compile --project ./project.inlang --outdir ./src/lib/paraglide

Or let the Vite plugin handle it automatically during dev/build.