Controller was directly calling personRepository.save() for person creation. Extracted into PersonService.createPerson() to enforce Controller → Service → Repository layering. Also documented the layering rules in CLAUDE.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6.5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Familienarchiv is a family document archival system — a full-stack web app for digitizing, organizing, and searching family documents. Key features: file uploads (stored in MinIO/S3), metadata management, Excel batch import, full-text search, conversation threads between family members, and role-based access control.
Collaboration Principles
Be honest and objective: Evaluate all suggestions, ideas, and feedback on their technical merits. Don't be overly complimentary or sycophantic. If something doesn't make sense, doesn't align with best practices, or could be improved, say so directly and constructively. Technical accuracy and project quality take precedence over being agreeable.
Core Workflow: Research → Plan → Implement → Validate
Start every feature with: "Let me research the codebase and create a plan before implementing."
- Research - Understand existing patterns and architecture
- Plan - Propose approach and verify with you
- Implement - Build with tests and error handling
- Validate - ALWAYS run formatters, linters, and tests after implementation
- Whenever working on a feature or issue, let's always come up with a plan first, then save it to a file called
/.agent/current-plan.md, before getting started with code changes. Update this file as the work progresses. - Let's use pure functions where possible to improve readability and testing.
Stack
- Backend: Spring Boot 4.0 (Java 21, Maven, Jetty, JPA/Hibernate, Flyway, Spring Security, Spring Session JDBC)
- Frontend: SvelteKit 2 with Svelte 5, TypeScript, Tailwind CSS 4, Paraglide.js (i18n: de/en/es)
- Database: PostgreSQL 16
- Object Storage: MinIO (S3-compatible)
- Infrastructure: Docker Compose
Common Commands
Running the Full Stack
# From repo root — starts PostgreSQL, MinIO, and Spring Boot backend
docker-compose up -d
Backend (Spring Boot)
cd backend
./mvnw spring-boot:run # Run locally
./mvnw clean package # Build JAR (with tests)
./mvnw clean package -DskipTests
./mvnw test # Run all tests
./mvnw test -Dtest=ClassName # Run a single test class
Frontend (SvelteKit)
cd frontend
npm install
npm run dev # Dev server (port 3000)
npm run build # Production build
npm run preview # Preview production build
npm run lint # Prettier + ESLint check
npm run format # Auto-fix formatting
npm run check # svelte-check (type checking)
npm run test # Vitest unit tests
Architecture
Backend (backend/src/main/java/org/raddatz/familienarchiv/)
Layered architecture:
model/— JPA entities:Document,Person,AppUser,UserGroup,Tag,DocumentStatus(enum: PLACEHOLDER → UPLOADED → TRANSCRIBED → REVIEWED → ARCHIVED)repository/— Spring Data repositories +DocumentSpecificationsfor complex filtered queriesservice/— Core business logic:DocumentService(uploads, search, Excel import),FileService(MinIO/S3),ExcelService,MassImportService,UserServicecontroller/— REST endpoints:DocumentController,PersonController,UserController,AdminController,GroupController,TagControllersecurity/—SecurityConfig(HTTP Basic + form login, CSRF disabled),PermissionAspect(AOP enforcement of@RequirePermission),CustomUserDetailsServiceconfig/—MinioConfig(creates S3Client, validates connectivity on startup),AsyncConfig
Database migrations live in src/main/resources/db/migration/ (Flyway). Configuration in src/main/resources/application.properties — most values injected from environment variables (DB credentials, MinIO endpoint/credentials/bucket, upload limits, Excel column mappings).
Frontend (backend/workspaces/frontend/src/)
hooks.server.ts— Central middleware: readsauth_tokencookie, injects it into all API calls to the backend, loads current user contextroutes/— File-based routing. Main pages:/(search/home),/documents/[id],/documents/[id]/edit,/persons,/persons/[id],/conversations,/admin,/loginroutes/api/— SvelteKit API endpoints for typeahead (persons, tags) — these call the Spring Boot backendlib/components/—PersonTypeahead.svelte,TagInput.sveltemessages/— Paraglide.js translation files (de.json,en.json,es.json)
Authentication: form login → backend sets session → auth_token cookie → hooks.server.ts injects into all backend requests.
Backend Layering Rules
Strict layering must be respected at all times:
Controller → Service → Repository → DB
- Controllers must never inject or call repositories directly. All business logic goes through a service.
- Services must never reach into another domain's repository directly. If Service A needs data owned by domain B, it calls Service B — not Repository B.
- ✅
DocumentService→PersonService.findById()→PersonRepository - ❌
DocumentService→PersonRepository(bypasses the service layer)
- ✅
- This keeps domain boundaries clear and business logic testable in isolation.
Key Design Patterns
- Search:
DocumentSpecifications(Spring Data JPA Specification pattern) enables composable, dynamic query building for the document search endpoint - Permissions:
@RequirePermissionannotation processed byPermissionAspect(AOP) — checks user'sUserGrouppermissions at the method level - Excel Import: Configurable column index mapping in
application.properties;ExcelServiceparses →MassImportServiceupserts documents - File Storage:
FileServicewraps AWS SDK v2S3Clientwith path-style access for MinIO compatibility
Infrastructure
The docker-compose.yml at the repo root orchestrates everything. A MinIO MC helper container runs at startup to create the archive-documents bucket and set permissions. The backend container depends on both db and minio being healthy before starting.
API Testing
HTTP test files are in backend/api_tests/ (Document.http, User.http) for use with the VS Code REST Client extension.
Dev Container
A .devcontainer/ config is available (Java 21 + Node 24, with ports 8080 and 3000 forwarded). Use VS Code's "Reopen in Container" to get a pre-configured environment with Spring Boot Tools, Lombok support, and database/MinIO services running.