# 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 │ ├── aktivitaeten/ # Unified activity feed (Chronik) │ ├── admin/ # User, group, tag, OCR, system management │ ├── api/ # Internal API proxies (server-side only) │ ├── geschichten/ # Stories (list, [id], [id]/edit, new) │ ├── stammbaum/ # Family tree │ ├── enrich/ # Enrichment workflow ([id], done) │ ├── hilfe/transkription/ # Transcription help page │ ├── profile/ # User profile settings │ ├── users/[id]/ # Public user profile page │ ├── login/ logout/ register/ │ └── forgot-password/ reset-password/ ├── 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//README.md`. ## API Client Pattern → See [CONTRIBUTING.md §Frontend API client](../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 ```typescript // +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](../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 tokens (defined in `layout.css`): | Token / Utility | CSS variable | Usage | | ---------------- | ---------------- | ------------------------------------------------------- | | `brand-navy` | `--palette-navy` | Tailwind utility — buttons, headers, primary text | | `brand-mint` | `--palette-mint` | Tailwind utility — accents, hover underlines, icons | | `--palette-sand` | `--palette-sand` | Palette constant only — use `bg-canvas` or `bg-surface` | Typography: - `font-serif` (Tinos) — body text, document titles, names - `font-sans` (Montserrat) — labels, metadata, UI chrome Card pattern for content sections: ```svelte

Section

``` ## Key UI Components → See per-domain READMEs: [`src/lib/person/README.md`](src/lib/person/README.md), [`src/lib/tag/README.md`](src/lib/tag/README.md), [`src/lib/document/README.md`](src/lib/document/README.md), [`src/lib/shared/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 ``. API client is at `$lib/shared/api.server`. ## How to Run ### Development ```bash cd frontend npm install npm run dev # Dev server on port 5173 ``` ### Build & Preview ```bash npm run build # Production build npm run preview # Preview production build ``` ### Code Quality ```bash npm run lint # Prettier + ESLint check npm run format # Auto-fix formatting npm run check # svelte-check (type checking) ``` ### Testing ```bash npm run test # Vitest unit + server tests (headless) npm run test:coverage # Coverage report (server + client) 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`: ```bash 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: ```bash npx @inlang/paraglide-js compile --project ./project.inlang --outdir ./src/lib/paraglide ``` Or let the Vite plugin handle it automatically during dev/build.