# ntrefftz/iw architecture

> Architecture diagram of the GitHub repository ntrefftz/iw, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-05-12). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/ntrefftz/iw
- Repository: https://github.com/ntrefftz/iw

## Overview

1. **Overall shape**
   - Frenemy is a **Spring Boot** application with a classic server-side architecture: **controllers** for HTTP endpoints, **services** for business logic, **JPA-style domain models/repositories** for persistence, and **Thymeleaf templates + static JS/CSS** for the UI.
   - The app is centered on three roles described in the README: **admin**, **host**, and **player**.

2. **Main entry and configuration**
   - `IwApplication` is the application bootstrap.
   - `AppConfig`, `StartupConfig`, `SecurityConfig`, `WebSocketConfig`, and `WebSocketSecurityConfig` define the main runtime boundaries: startup behavior, authentication/authorization, and real-time messaging.
   - `LoginSuccessHandler` and `IwUserDetailsService` plug the user model into Spring Security.

3. **Presentation layer**
   - There are two UI styles in the repo:
     - **Server-rendered pages** in `src/main/resources/templates` (`index`, `login`, `register`, `profile`, `lobby`, `game`, `admin`, etc.).
     - **Client-side behavior** in `src/main/resources/static/js` and `css`.
   - Thymeleaf fragments (`head`, `nav`, `footer`, `chat`) indicate a shared page layout with reusable UI components.

4. **HTTP controllers and page/API split**
   - Controllers are split by responsibility:
     - `RootController`, `UserController`, `LobbyController`, `AdminController` likely serve pages and user flows.
     - `ApiController`, `LobbyApiController`, `UnoApiController` expose JSON endpoints for dynamic interactions.
   - This suggests a mixed model: **full-page navigation for core flows** plus **AJAX-driven endpoints** for interactive features.

5. **Core service layer**
   - `LobbyService` and `UnoService` are the main business-logic boundaries.
   - `LobbyService` likely manages lobby creation/joining, player order, lobby state, and game selection.
   - `UnoService` manages the card game state and player actions.
   - `LobbyException` indicates domain-specific validation and workflow errors are handled in the service layer rather than in controllers.

6. **Domain model**
   - The `model` package contains the main entities and transfer objects:
     - Social/user data: `User`, `Friendship`, `FriendRequest`, `Message`, `Topic`.
     - Game data: `Game`, `GameMessage`, `Card`, `UnoState`, `UnoActionRequest`.
     - Utility/base abstractions: `Transferable`, `Lorem`.
   - `UnoStateConverter` shows that UNO game state is persisted/transformed as a structured value, not just held in memory.

7. **Persistence and seed data**
   - `GameRepository` is the main repository visible in the tree, implying persistent storage for available games and related metadata.
   - `LocalData` and `src/main/resources/import.sql` indicate bootstrap/seed data is loaded at startup.
   - The README confirms initial data includes users (`a`, `b`, `c`, `d`), friendships, friendship scores, and match rankings so profile pages are not empty on first run.

8. **Authentication and authorization boundaries**
   - The app uses role-based access control around the three user types, with admin features separated from normal user flows.
   - Security is integrated both for standard HTTP sessions and for WebSocket traffic, which matters because the app has real-time lobby/chat/game updates.
   - `credentials.json.template` suggests there is some environment-specific credential/config injection for deployment or external integration.

9. **Real-time communication**
   - `WebSocketConfig` and `WebSocketSecurityConfig` indicate a dedicated real-time channel for lobby/chat/game updates.
   - Static JS files such as `stomp.js`, `chat.js`, `lobby.js`, and `game.js` support this front-end messaging model.
   - This is likely the main path for live state synchronization while users are inside lobbies or active games.

10. **Frontend behavior**
   - The browser-side code is organized by feature: `admin.js`, `friend-requests.js`, `profile.js`, `game.js`, `lobby.js`, `chat.js`, plus shared helpers like `util.js` and `iw.js`.
   - This means most interactive UI behavior is feature-scoped rather than centralized, which helps keep the lobby/game/admin flows separate.

11. **Administrative and social subsystems**
   - `AdminController` and `admin.html` form the management plane for games and users.
   - `UserController` plus the profile/friend-request scripts support the social layer: friendships, friend requests, affinity/rankings, and profile viewing.
   - The README explicitly positions the app as a friendship-testing social game platform, so the social graph is a first-class feature, not just auxiliary data.

12. **Testing and delivery**
   - Tests are split into:
     - **internal tests** under `src/test/java/internal/...`
     - **external/behavioral tests** using feature files and `ExternalRunner`
     - a focused unit test for `UnoStateConverter`
   - The presence of `karate-config.js` and `.feature` files suggests end-to-end API/UI behavior tests.
   - `deploy.py` is a repo-level deployment helper, while Maven (`pom.xml`) is the main build/runtime toolchain.

13. **Architecture summary for a diagram**
   - A good diagram would show:
     - **Browser/UI** on the left
     - **HTTP controllers** and **WebSocket endpoints** in the middle
     - **services** underneath as the business layer
     - **domain models/repository + database** on the right/bottom
   - The key special-case flows are:
     - **login/security** through Spring Security
     - **lobby/chat/game live updates** through WebSockets
     - **admin/user management** through dedicated controllers/pages
     - **UNO state handling** through `UnoService` and `UnoStateConverter`.

Main entry points: [`src/main/resources/static/js/iw.js`](https://github.com/ntrefftz/iw/blob/main/src/main/resources/static/js/iw.js) (Client JS), [`src/main/java/es/ucm/fdi/iw/WebSocketConfig.java`](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/WebSocketConfig.java) (WebSocket), [`src/main/resources/templates/index.html`](https://github.com/ntrefftz/iw/blob/main/src/main/resources/templates/index.html) (Templates), [`src/main/java/es/ucm/fdi/iw/IwApplication.java`](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/IwApplication.java) (Boot app)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_grp_ui["Presentation"]
  node_node_templates["Templates<br/>thymeleaf views<br/>[index.html]"]
  node_node_staticjs["Client JS<br/>browser scripts<br/>[iw.js]"]
  node_node_staticcss["Styles<br/>[custom.css]"]
end

subgraph group_grp_web["Web layer"]
  node_node_rootctl["Root<br/>page controller"]
  node_node_userctl["Users<br/>page controller"]
  node_node_lobbyctl["Lobby pages<br/>page controller"]
  node_node_adminctl["Admin<br/>page controller"]
  node_node_api["API<br/>json controller<br/>[ApiController.java]"]
  node_node_lobbyapi["Lobby API<br/>json controller"]
  node_node_unoapi["UNO API<br/>game controller"]
end

subgraph group_grp_core["Core logic"]
  node_node_iwapp(("Boot app<br/>[IwApplication.java]"))
  node_node_appconfig["Config<br/>[AppConfig.java]"]
  node_node_startup["Startup<br/>[StartupConfig.java]"]
  node_node_security["Security<br/>auth config"]
  node_node_wsconfig["WebSocket<br/>ws config"]
  node_node_wssecurity["WS security<br/>ws auth"]
  node_node_loginhandler["Login success<br/>auth handler"]
  node_node_udetails["User details<br/>user service"]
  node_node_lobbyservice["Lobby service<br/>game service<br/>[LobbyService.java]"]
  node_node_unoservice["UNO service<br/>game service<br/>[UnoService.java]"]
  node_node_lobbyexc{{"Lobby error<br/>domain exception"}}
end

subgraph group_grp_domain["Domain data"]
  node_node_user[("User<br/>entity<br/>[User.java]")]
  node_node_game[("Game<br/>entity<br/>[Game.java]")]
  node_node_unostate["UNO state<br/>value object<br/>[UnoState.java]"]
  node_node_unoconv["State converter<br/>jpa converter"]
  node_node_gamerepo[("Game repo")]
  node_node_localdata["Seed data<br/>bootstrap data<br/>[LocalData.java]"]
end

node_node_iwapp -->|"loads"| node_node_appconfig
node_node_iwapp -->|"initializes"| node_node_startup
node_node_iwapp -->|"enables"| node_node_security
node_node_iwapp -->|"enables"| node_node_wsconfig
node_node_security -->|"uses"| node_node_udetails
node_node_security -->|"delegates"| node_node_loginhandler
node_node_wsconfig -->|"protects"| node_node_wssecurity
node_node_rootctl -->|"renders"| node_node_templates
node_node_userctl -->|"renders"| node_node_templates
node_node_lobbyctl -->|"renders"| node_node_templates
node_node_adminctl -->|"renders"| node_node_templates
node_node_rootctl -->|"drives"| node_node_staticjs
node_node_userctl -->|"drives"| node_node_staticjs
node_node_lobbyctl -->|"drives"| node_node_staticjs
node_node_adminctl -->|"drives"| node_node_staticjs
node_node_api -->|"uses"| node_node_lobbyservice
node_node_lobbyapi -->|"uses"| node_node_lobbyservice
node_node_unoapi -->|"uses"| node_node_unoservice
node_node_lobbyservice -->|"throws"| node_node_lobbyexc
node_node_lobbyservice -->|"reads/writes"| node_node_gamerepo
node_node_unoservice -->|"manages"| node_node_unostate
node_node_unoservice -->|"persists via"| node_node_unoconv
node_node_unoconv -->|"converts"| node_node_unostate
node_node_gamerepo -->|"stores"| node_node_game
node_node_localdata -->|"seeds"| node_node_user
node_node_localdata -->|"seeds"| node_node_game
node_node_localdata -->|"loads into"| node_node_gamerepo
node_node_staticjs -->|"connects to"| node_node_wsconfig
node_node_staticcss -->|"styles"| node_node_templates
node_node_lobbyapi -->|"broadcasts"| node_node_wsconfig
node_node_unoapi -->|"broadcasts"| node_node_wsconfig

click node_node_iwapp "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/IwApplication.java"
click node_node_appconfig "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/AppConfig.java"
click node_node_startup "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/StartupConfig.java"
click node_node_security "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/SecurityConfig.java"
click node_node_wsconfig "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/WebSocketConfig.java"
click node_node_wssecurity "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/WebSocketSecurityConfig.java"
click node_node_loginhandler "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/LoginSuccessHandler.java"
click node_node_udetails "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/IwUserDetailsService.java"
click node_node_rootctl "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/controller/RootController.java"
click node_node_userctl "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/controller/UserController.java"
click node_node_lobbyctl "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/controller/LobbyController.java"
click node_node_adminctl "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/controller/AdminController.java"
click node_node_api "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/controller/ApiController.java"
click node_node_lobbyapi "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/controller/LobbyApiController.java"
click node_node_unoapi "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/controller/UnoApiController.java"
click node_node_lobbyservice "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/LobbyService.java"
click node_node_unoservice "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/UnoService.java"
click node_node_lobbyexc "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/LobbyException.java"
click node_node_user "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/model/User.java"
click node_node_game "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/model/Game.java"
click node_node_unostate "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/model/UnoState.java"
click node_node_unoconv "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/model/converters/UnoStateConverter.java"
click node_node_gamerepo "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/GameRepository.java"
click node_node_localdata "https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/LocalData.java"
click node_node_templates "https://github.com/ntrefftz/iw/blob/main/src/main/resources/templates/index.html"
click node_node_staticjs "https://github.com/ntrefftz/iw/blob/main/src/main/resources/static/js/iw.js"
click node_node_staticcss "https://github.com/ntrefftz/iw/blob/main/src/main/resources/static/css/custom.css"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_node_templates,node_node_staticjs,node_node_staticcss toneBlue
class node_node_rootctl,node_node_userctl,node_node_lobbyctl,node_node_adminctl,node_node_api,node_node_lobbyapi,node_node_unoapi toneAmber
class node_node_iwapp,node_node_appconfig,node_node_startup,node_node_security,node_node_wsconfig,node_node_wssecurity,node_node_loginhandler,node_node_udetails,node_node_lobbyservice,node_node_unoservice,node_node_lobbyexc toneMint
class node_node_user,node_node_game,node_node_unostate,node_node_unoconv,node_node_gamerepo,node_node_localdata toneRose
```

## Components

### Presentation

Server-rendered pages and browser-side behavior

- [Templates](https://github.com/ntrefftz/iw/blob/main/src/main/resources/templates/index.html): thymeleaf views · Server-rendered pages and fragments · `src/main/resources/templates/index.html`
- [Client JS](https://github.com/ntrefftz/iw/blob/main/src/main/resources/static/js/iw.js): browser scripts · Feature scripts and shared UI logic · `src/main/resources/static/js/iw.js`
- [Styles](https://github.com/ntrefftz/iw/blob/main/src/main/resources/static/css/custom.css): browser styles · Page and shared styling assets · `src/main/resources/static/css/custom.css`

### Web layer

HTTP controllers and real-time endpoints

- [Root](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/controller/RootController.java): page controller · Landing pages and shared navigation · `src/main/java/es/ucm/fdi/iw/controller/RootController.java`
- [Users](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/controller/UserController.java): page controller · Profile and social flows · `src/main/java/es/ucm/fdi/iw/controller/UserController.java`
- [Lobby pages](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/controller/LobbyController.java): page controller · Lobby and game entry pages · `src/main/java/es/ucm/fdi/iw/controller/LobbyController.java`
- [Admin](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/controller/AdminController.java): page controller · Administrative pages and management · `src/main/java/es/ucm/fdi/iw/controller/AdminController.java`
- [API](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/controller/ApiController.java): json controller · Shared JSON endpoints · `src/main/java/es/ucm/fdi/iw/controller/ApiController.java`
- [Lobby API](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/controller/LobbyApiController.java): json controller · Lobby state and join/leave actions · `src/main/java/es/ucm/fdi/iw/controller/LobbyApiController.java`
- [UNO API](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/controller/UnoApiController.java): game controller · UNO actions and game-state endpoints · `src/main/java/es/ucm/fdi/iw/controller/UnoApiController.java`

### Core logic

Business services and security/runtime wiring

- [Boot app](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/IwApplication.java): spring-boot app · Application entry point · `src/main/java/es/ucm/fdi/iw/IwApplication.java`
- [Config](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/AppConfig.java): spring config · Core application configuration · `src/main/java/es/ucm/fdi/iw/AppConfig.java`
- [Startup](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/StartupConfig.java): startup config · Startup-time initialization and wiring · `src/main/java/es/ucm/fdi/iw/StartupConfig.java`
- [Security](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/SecurityConfig.java): auth config · HTTP authentication and authorization · `src/main/java/es/ucm/fdi/iw/SecurityConfig.java`
- [WebSocket](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/WebSocketConfig.java): ws config · Real-time messaging configuration · `src/main/java/es/ucm/fdi/iw/WebSocketConfig.java`
- [WS security](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/WebSocketSecurityConfig.java): ws auth · Security rules for WebSocket traffic · `src/main/java/es/ucm/fdi/iw/WebSocketSecurityConfig.java`
- [Login success](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/LoginSuccessHandler.java): auth handler · Post-login routing and session setup · `src/main/java/es/ucm/fdi/iw/LoginSuccessHandler.java`
- [User details](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/IwUserDetailsService.java): user service · Spring Security user lookup · `src/main/java/es/ucm/fdi/iw/IwUserDetailsService.java`
- [Lobby service](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/LobbyService.java): game service · Lobby lifecycle and match coordination · `src/main/java/es/ucm/fdi/iw/LobbyService.java`
- [UNO service](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/UnoService.java): game service · UNO rules and state transitions · `src/main/java/es/ucm/fdi/iw/UnoService.java`
- [Lobby error](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/LobbyException.java): domain exception · Lobby workflow validation errors · `src/main/java/es/ucm/fdi/iw/LobbyException.java`

### Domain data

Entities, state, repository, and bootstrapped data

- [User](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/model/User.java): entity · Application user and role model · `src/main/java/es/ucm/fdi/iw/model/User.java`
- [Game](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/model/Game.java): entity · Game metadata and ownership · `src/main/java/es/ucm/fdi/iw/model/Game.java`
- [UNO state](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/model/UnoState.java): value object · Serialized game state · `src/main/java/es/ucm/fdi/iw/model/UnoState.java`
- [State converter](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/model/converters/UnoStateConverter.java): jpa converter · Persists UNO state values · `src/main/java/es/ucm/fdi/iw/model/converters/UnoStateConverter.java`
- [Game repo](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/GameRepository.java): repository · Persistence access for games · `src/main/java/es/ucm/fdi/iw/GameRepository.java`
- [Seed data](https://github.com/ntrefftz/iw/blob/main/src/main/java/es/ucm/fdi/iw/LocalData.java): bootstrap data · Initial in-memory/bootstrap data · `src/main/java/es/ucm/fdi/iw/LocalData.java`

## Connections

- Boot app → Config: loads · Bootstraps application configuration
- Boot app → Startup: initializes · Runs startup setup
- Boot app → Security: enables · Activates HTTP security
- Boot app → WebSocket: enables · Activates WebSocket runtime
- Security → User details: uses · Loads users for authentication
- Security → Login success: delegates · Handles post-login routing
- WebSocket → WS security: protects · Secures real-time channels
- Root → Templates: renders · Serves shared pages
- Users → Templates: renders · Serves profile/social pages
- Lobby pages → Templates: renders · Serves lobby/game pages
- Admin → Templates: renders · Serves admin pages
- Root → Client JS: drives · Page scripts support interactions
- Users → Client JS: drives · Social UI scripts support interactions
- Lobby pages → Client JS: drives · Lobby/game scripts support interactions
- Admin → Client JS: drives · Admin scripts support interactions
- API → Lobby service: uses · Shared API logic
- Lobby API → Lobby service: uses · Lobby operations
- UNO API → UNO service: uses · UNO actions and rules
- Lobby service → Lobby error: throws · Reports workflow errors
- Lobby service → Game repo: reads/writes · Persists lobby/game metadata
- UNO service → UNO state: manages · Updates game state
- UNO service → State converter: persists via · Stores UNO state as a value
- State converter → UNO state: converts · Maps state to storage
- Game repo → Game: stores · Game persistence model
- Seed data → User: seeds · Initial users and social graph
- Seed data → Game: seeds · Initial game data
- Seed data → Game repo: loads into · Bootstrap repository content
- Client JS → WebSocket: connects to · Browser scripts consume realtime updates
- Styles → Templates: styles · Presentation assets for pages
- Lobby API → WebSocket: broadcasts · Lobby updates over realtime channel
- UNO API → WebSocket: broadcasts · Game updates over realtime channel
