Backend: Spring Boot 3.5.11 on Java 25, Maven with wrapper, hexagonal architecture package layout (domain/application/adapter/config), health endpoint with integration test. Originally planned for Spring Boot 4.0 but pivoted due to massive package reorganization in 4.0 (see addenda in research and plan docs). Frontend: Vue 3 scaffolded via create-vue with TypeScript, Vue Router, Vitest, ESLint, Prettier. Pivoted from Svelte due to ecosystem maturity concerns (broken router ecosystem for Svelte 5). Also: extended .gitignore for Java/Maven and Node/Vue artifacts, updated CLAUDE.md with tech stack, build commands, agent documentation sections, and document integrity rule. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
20 KiB
date, git_commit, branch, topic, tags, status
| date | git_commit | branch | topic | tags | status | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2026-03-04T00:19:03+01:00 | 7b460dd322 |
master | T-1: Initialize monorepo structure — Tech stack research |
|
complete |
Research: T-1 — Initialize Monorepo Structure
Research Question
What are the current versions, scaffolding approaches, and architectural patterns needed to implement T-1 (Initialize monorepo structure) with the specified tech stack: Java (latest LTS), Spring Boot, Maven, hexagonal/onion architecture backend + Svelte with Vite frontend?
Summary
This research covers all technical aspects needed for T-1. The spec requires a monorepo with backend/ and frontend/ directories, both building successfully as empty scaffolds. The key findings and open decisions are:
- Java 25 is the current LTS (Sep 2025). Spring Boot 4.0.3 is the latest stable — but 3.5.x is more battle-tested. This is an architectural decision.
- Svelte 5 is stable (since Oct 2024). The SPA router ecosystem for plain Svelte 5 is weak — SvelteKit in SPA mode is the pragmatic alternative.
- Hexagonal architecture: Single Maven module with package-level separation + ArchUnit enforcement. Base package
com.fete. - TypeScript for the frontend is recommended but is a decision point.
Detailed Findings
1. Java Version
Java 25 (LTS) — released September 16, 2025.
- Premier support through Sep 2030, extended support through Sep 2033.
- Supersedes Java 21 (Sep 2023) as the current LTS.
- Java 21 is still supported but free updates end Sep 2026.
- Next LTS: Java 29 (Sep 2027).
Recommendation: Java 25. Longest support runway, both Spring Boot 3.5 and 4.0 support it.
2. Spring Boot Version
Two actively supported lines as of March 2026:
| Version | Latest Patch | OSS Support Ends | Java Baseline | Key Dependencies |
|---|---|---|---|---|
| 4.0.x | 4.0.3 | Dec 2026 | Java 17+ (up to 25) | Spring Framework 7.0, Jakarta EE 11, Hibernate 7.1, Jackson 3.0, Tomcat 11.0 |
| 3.5.x | 3.5.11 | Jun 2026 | Java 17+ (up to 25) | Spring Framework 6.x, Jakarta EE 10, Hibernate 6.x, Jackson 2.x, Tomcat 10.x |
Trade-offs:
| Factor | Spring Boot 4.0 | Spring Boot 3.5 |
|---|---|---|
| Support runway | Dec 2026 (longer) | Jun 2026 (shorter) |
| Ecosystem maturity | Jackson 3.0 + Hibernate 7.1 are new major versions; fewer community examples | Battle-tested, large ecosystem of examples |
| Migration burden | None (greenfield) | None (greenfield) |
| Forward-looking | Yes | Will need migration to 4.x eventually |
Decision needed: Spring Boot 4.0 (forward-looking) vs. 3.5 (more battle-tested). Both support Java 25.
3. Maven
- Maven version: 3.9.12 (latest stable; Maven 4.0.0 is still RC).
- Maven Wrapper: Yes, include it. Modern "only-script" distribution — no binary JAR in repo. Scripts
mvnw/mvnw.cmd+.mvn/wrapper/maven-wrapper.propertiesare committed. - Benefits: deterministic builds in Docker, no Maven pre-install requirement for contributors or CI.
Minimal dependencies for Spring Boot + PostgreSQL:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.3</version> <!-- or 3.5.11 -->
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Note: For the empty scaffold (T-1), JPA autoconfig must be excluded or deferred since there's no DB yet. Either omit spring-boot-starter-data-jpa until T-4, or add spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration to application.properties.
4. Svelte + Vite Frontend
Current versions:
- Svelte: 5.53.6 (stable since Oct 2024, runes-based reactivity)
- Vite: 7.3.1 (stable; Vite 8 is in beta)
Svelte 5 key changes from Svelte 4:
- Reactive state:
let count = $state(0)(explicit rune) instead of implicitlet count = 0 - Derived values:
$derived()replaces$:blocks - Props:
$props()replacesexport let - Reactivity works in
.svelte.tsfiles too (not just components)
5. SvelteKit vs. Plain Svelte — Decision Point
The spec says "Svelte with Vite as bundler" for an SPA with a separate REST backend.
Option A: Plain Svelte + Vite + third-party router
| Pro | Con |
|---|---|
| Simpler mental model | Router ecosystem broken for Svelte 5: svelte-spa-router has no Svelte 5 support (issue #318) |
| Literal spec wording | Only unmaintained/low-adoption alternatives exist |
| No unused SSR concepts | Violates dependency statute ("actively maintained") |
Option B: SvelteKit in SPA mode (adapter-static + ssr: false)
| Pro | Con |
|---|---|
| Built-in file-based routing (maintained by Svelte team) | Has SSR concepts that exist but are unused |
| First-class Vitest integration (T-4 requirement) | Slightly larger framework footprint |
| SPA config is 3 lines of code | SEO concerns (irrelevant for this app) |
| Output is static HTML/JS/CSS — no Node.js runtime needed | |
npx sv create scaffolds TS/ESLint/Vitest in one step |
SPA configuration (total effort):
npm i -D @sveltejs/adapter-staticsvelte.config.js:adapter: adapter({ fallback: '200.html' })src/routes/+layout.js:export const ssr = false;
Decision needed: SvelteKit in SPA mode (pragmatic, solves the router problem) vs. plain Svelte + Vite (minimalist, but router ecosystem is a real problem).
6. TypeScript vs. JavaScript — Decision Point
Arguments for TypeScript:
- Java backend is strongly typed; TS catches API contract drift at compile time.
- Svelte 5 has first-class TS support, including TS in markup.
- The API client layer (T-4) benefits most from type safety.
- Zero-config in both SvelteKit and the
svelte-tsVite template. - Rich Harris: "TypeScript for apps, JSDoc for libraries." This is an app.
Arguments against:
- KISS/grugbrain principle — TS adds cognitive overhead.
- Svelte's compiler already catches many errors.
Verdict from research: TS overhead in Svelte 5 is minimal (let count: number = $state(0) vs. let count = $state(0)). The real value is in the API client layer and shared types.
7. Node.js Version
| Version | Status | End of Life |
|---|---|---|
| Node.js 24 | Active LTS | ~April 2028 |
| Node.js 22 | Active LTS | April 2027 |
| Node.js 20 | Maintenance LTS | April 2026 (EOL imminent) |
Recommendation: Target Node.js 22 LTS as minimum. Docker image should use node:22-alpine.
8. Hexagonal Architecture — Package Structure
Approach: Single Maven module with package-level separation. Multi-module Maven is overkill for a small app. ArchUnit test enforces dependency rules.
Package structure:
com.fete
├── FeteApplication.java # @SpringBootApplication
├── domain/
│ ├── model/ # Entities, value objects (plain Java, no framework annotations)
│ └── port/
│ ├── in/ # Driving port interfaces (use cases)
│ └── out/ # Driven port interfaces (repositories)
├── application/
│ └── service/ # Use case implementations (@Service)
├── adapter/
│ ├── in/
│ │ └── web/ # REST controllers, DTOs, mappers
│ └── out/
│ └── persistence/ # JPA entities, Spring Data repos, mappers
└── config/ # @Configuration classes
Dependency flow (strict):
domain → nothing
application → domain only
adapter → application + domain
config → everything (wiring)
Spring annotations by layer:
| Layer | Annotations | Rationale |
|---|---|---|
domain.model |
None | Plain Java — no framework coupling |
domain.port |
None | Plain Java interfaces |
application.service |
@Service only |
Pragmatic compromise for component scanning |
adapter.in.web |
@RestController, @GetMapping, etc. |
Framework adapter layer |
adapter.out.persistence |
@Entity, @Repository, @Table, etc. |
Framework adapter layer |
config |
@Configuration, @Bean |
Wiring layer |
Domain purity: Persistence has its own JPA entity classes (e.g., EventJpaEntity) separate from domain model classes. Mappers convert between them.
Empty directory markers: Use package-info.java in each leaf package. Documents package purpose, allows Git to track the directory, and aids component scanning.
Base package: com.fete (Maven convention, clean, short).
9. .gitignore
The existing .gitignore covers IDE files (.idea/, .vscode/, *.iml), OS files (.DS_Store, Thumbs.db), and Claude settings. The following sections need to be added:
Java/Maven:
*.class,*.jar,*.war,*.ear,*.nar— compiled artifactstarget/— Maven build output- Maven release plugin files (
pom.xml.tag,pom.xml.releaseBackup, etc.) .mvn/wrapper/maven-wrapper.jar— downloaded automatically- Eclipse files (
.classpath,.project,.settings/,.factorypath) - Spring Boot (
.springBeans,.sts4-cache) - Java crash logs (
hs_err_pid*,replay_pid*) *.log
Node.js/Svelte/Vite:
node_modules/dist/,build/— build output.svelte-kit/— SvelteKit generated filesvite.config.js.timestamp-*,vite.config.ts.timestamp-*— Vite temp files.env,.env.*(but NOT.env.example)npm-debug.log*
Editor files:
*.swp,*.swo,*~— Vim/editor backup files\#*\#,.#*— Emacs
Committed (NOT ignored):
mvnw,mvnw.cmd,.mvn/wrapper/maven-wrapper.propertiespackage-lock.json
10. Existing Repository State
The repository currently contains:
CLAUDE.md— Project statutesREADME.md— With tech stack docs and docker-compose exampleLICENSE— GPL.gitignore— Partial (IDE + OS only)Ideen.md— German idea documentspec/— User stories, personas, setup tasks, implementation phases.ralph/— Ralph loop infrastructureralph.sh— Ralph loop runnerreview-findings.md— Review notes
No backend/ or frontend/ directories exist yet. No Dockerfile exists yet (listed in README project structure, but deferred to T-2).
Decisions Required Before Implementation
These are architectural decisions that require approval per CLAUDE.md governance statutes:
| # | Decision | Options | Recommendation |
|---|---|---|---|
| 1 | Spring Boot version | 4.0.3 (latest, longer support) vs. 3.5.11 (battle-tested, shorter support) | 4.0.3 — greenfield project, no migration burden, longer support |
| 2 | SvelteKit vs. plain Svelte | SvelteKit SPA mode vs. plain Svelte + third-party router | SvelteKit SPA mode — router ecosystem for plain Svelte 5 is broken |
| 3 | TypeScript vs. JavaScript | TypeScript (type safety on API boundary) vs. JavaScript (simpler) | TypeScript — minimal overhead in Svelte 5, catches API contract drift |
| 4 | Spring Boot JPA in T-1? | Include spring-boot-starter-data-jpa now (exclude autoconfig) vs. add it in T-4 |
Defer to T-4 — T-1 is "empty scaffold", JPA needs a datasource |
Code References
spec/setup-tasks.md— T-1 acceptance criteriaspec/implementation-phases.md:9-14— Phase 0 task orderCLAUDE.md:36-43— Dependency statutesIdeen.md:76-78— Tech stack decisions (already made).gitignore— Current state (needs extension)README.md:112-119— Documented project structure (target)
Architecture Documentation
Target Repository Layout (after T-1)
fete/
├── backend/
│ ├── pom.xml
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── .mvn/wrapper/maven-wrapper.properties
│ └── src/
│ ├── main/
│ │ ├── java/com/fete/
│ │ │ ├── FeteApplication.java
│ │ │ ├── domain/model/ (package-info.java)
│ │ │ ├── domain/port/in/ (package-info.java)
│ │ │ ├── domain/port/out/ (package-info.java)
│ │ │ ├── application/service/ (package-info.java)
│ │ │ ├── adapter/in/web/ (package-info.java)
│ │ │ ├── adapter/out/persistence/(package-info.java)
│ │ │ └── config/ (package-info.java)
│ │ └── resources/
│ │ └── application.properties
│ └── test/java/com/fete/
│ └── FeteApplicationTest.java
├── frontend/
│ ├── package.json
│ ├── package-lock.json
│ ├── svelte.config.js
│ ├── vite.config.ts
│ ├── tsconfig.json
│ ├── src/
│ │ ├── app.html
│ │ ├── routes/
│ │ │ ├── +layout.js (ssr = false)
│ │ │ └── +page.svelte
│ │ └── lib/
│ └── static/
├── spec/
├── .gitignore (extended)
├── CLAUDE.md
├── README.md
├── LICENSE
└── Ideen.md
Build Commands (Target State)
| What | Command |
|---|---|
| Backend build | cd backend && ./mvnw package |
| Backend test | cd backend && ./mvnw test |
| Frontend install | cd frontend && npm install |
| Frontend build | cd frontend && npm run build |
| Frontend test | cd frontend && npm test |
| Frontend dev | cd frontend && npm run dev |
Open Questions
All resolved — see Follow-up Research below.
Follow-up Research: Frontend Pivot to Vue 3 (2026-03-04)
Context
During decision review, the developer raised concerns about the Svelte 5 ecosystem maturity (specifically the broken third-party router situation signaling a smaller, less mature ecosystem). After comparing Svelte 5 vs Vue 3 on ecosystem size, community support, team size, and stability, the decision was made to pivot from Svelte to Vue 3.
Rationale
- Vue 3 has a significantly larger ecosystem and community
- Official, battle-tested packages for all needs (Vue Router, Pinia, Vitest)
- Vite was created by Evan You (Vue's creator) — first-class integration
- Vue 3 Composition API is modern and elegant while being mature (stable since 2020)
- Larger team, broader funding, more StackOverflow answers and tutorials
Vue 3 Stack — Research Findings
Current versions (March 2026):
| Package | Version | Notes |
|---|---|---|
| Vue | 3.5.29 | Stable. Vue 3.6 (Vapor Mode) is in beta |
| Vue Router | 5.0.3 | Includes file-based routing from unplugin-vue-router. Drop-in from v4 for manual routes |
| Vite | 7.3.1 | Stable. Vite 8 (Rolldown) is in beta |
| Vitest | 4.0.18 | Stable. Browser Mode graduated from experimental |
| @vue/test-utils | 2.4.6 | Official component testing utilities |
| create-vue | 3.22.0 | Official scaffolding tool |
| Node.js | 24 LTS | Latest LTS, support through ~April 2028 |
Scaffolding: npm create vue@latest (official Vue CLI scaffolding). Interactive prompts offer TypeScript, Vue Router, Pinia, Vitest, ESLint, Prettier out of the box.
Selected options for fete:
- TypeScript: Yes
- Vue Router: Yes
- Pinia: No — Composition API (
ref/reactive) + localStorage is sufficient for this app's simple state - Vitest: Yes
- ESLint: Yes
- Prettier: Yes
- E2E testing: No (not needed for T-1)
Project structure (scaffolded by create-vue):
frontend/
├── public/
│ └── favicon.ico
├── src/
│ ├── assets/ # Static assets (CSS, images)
│ ├── components/ # Reusable components
│ ├── composables/ # Composition API composables (added manually)
│ ├── router/ # Vue Router config (index.ts)
│ ├── views/ # Route-level page components
│ ├── App.vue # Root component
│ └── main.ts # Entry point
├── index.html
├── package.json
├── tsconfig.json
├── tsconfig.app.json
├── tsconfig.node.json
├── vite.config.ts
├── eslint.config.js
├── .prettierrc.json
├── env.d.ts
└── README.md
Key conventions:
src/views/for route page components (notsrc/pages/— that's Nuxt)src/components/for reusable componentssrc/composables/for Composition API composables (e.g.,useStorage.ts)src/router/index.tsfor route definitions
Resolved Decisions
| # | Decision | Resolution |
|---|---|---|
| 1 | Spring Boot version | |
| 2 | Frontend framework | Vue 3 — pivot from Svelte due to ecosystem maturity concerns |
| 3 | TypeScript | Yes — confirmed by developer |
| 4 | Node.js version | 24 LTS (latest LTS) |
| 5 | Base package | de.fete (not com.fete) |
| 6 | JPA in T-1 | Defer to T-4 — T-1 is empty scaffold, JPA needs a datasource |
| 7 | State management | No Pinia — Composition API + localStorage sufficient |
Addendum: Spring Boot 4.0 → 3.5 Pivot (2026-03-04)
During T-1 implementation, Spring Boot 4.0.3 proved unworkable for the scaffold phase. The 4.0 release massively reorganized internal packages — test infrastructure classes (TestRestTemplate, AutoConfigureMockMvc, etc.) were moved into new modules with different package paths. The Spring Boot 4.0 Migration Guide did not cover these changes adequately, and resolving the issues required extensive trial-and-error with undocumented class locations and missing transitive dependencies.
Decision: Pivot to Spring Boot 3.5.11 (latest 3.5.x patch). This is the battle-tested line with OSS support through June 2026. Since this is a greenfield project, migrating to 4.x later (once the ecosystem and documentation have matured) is straightforward.
Impact: None on architecture or feature scope. The hexagonal package structure, dependency choices, and all other decisions remain unchanged. Only the Spring Boot parent version in pom.xml changed.
Updated Target Repository Layout
fete/
├── backend/
│ ├── pom.xml
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── .mvn/wrapper/maven-wrapper.properties
│ └── src/
│ ├── main/
│ │ ├── java/de/fete/
│ │ │ ├── FeteApplication.java
│ │ │ ├── domain/model/ (package-info.java)
│ │ │ ├── domain/port/in/ (package-info.java)
│ │ │ ├── domain/port/out/ (package-info.java)
│ │ │ ├── application/service/ (package-info.java)
│ │ │ ├── adapter/in/web/ (package-info.java)
│ │ │ ├── adapter/out/persistence/(package-info.java)
│ │ │ └── config/ (package-info.java)
│ │ └── resources/
│ │ └── application.properties
│ └── test/java/de/fete/
│ └── FeteApplicationTest.java
├── frontend/
│ ├── public/
│ ├── src/
│ │ ├── assets/
│ │ ├── components/
│ │ ├── composables/
│ │ ├── router/index.ts
│ │ ├── views/
│ │ ├── App.vue
│ │ └── main.ts
│ ├── index.html
│ ├── package.json
│ ├── package-lock.json
│ ├── tsconfig.json
│ ├── vite.config.ts
│ └── eslint.config.js
├── spec/
├── .gitignore (extended)
├── CLAUDE.md
├── README.md
├── LICENSE
└── Ideen.md