A full-stack web application for managing amateur football tournaments: teams, players, matches, results, and standings — with public browsing, user comments, and full admin management.
Originally built as a university project for the Sistemi Informativi su Web (Web Information Systems) course at Roma Tre University, Italy. The academic requirements were in Italian, so the application's UI and database content remain in Italian, while this documentation is in English for portfolio purposes.
- Browse tournaments, standings, fixtures, and results — no login required
- Browse teams and squads, with pagination
- Registered users can post and edit their own comments on matches
- Full authentication and role-based authorization (public visitor / registered user / admin)
- Admin dashboard: full CRUD for tournaments, teams, players, referees, and matches
- Standings computed dynamically from match results
- A React micro-frontend consuming a REST API for the live standings table
- Custom UI (no template), consistent design system, responsive layout
Tournament detail (standings, fixtures, results):

| Layer | Technology |
|---|---|
| Backend | Spring Boot 4 (Java 17) |
| Persistence | JPA / Hibernate |
| Database | PostgreSQL |
| Server-side views | Thymeleaf |
| Client-side widget | React (Vite) |
| Security | Spring Security (form login, BCrypt password hashing) |
| Build | Maven |
Seven entities modeling the tournament domain:
| Entity | Key attributes | Relationships |
|---|---|---|
| Tournament | name, year, description | many-to-many with Team |
| Team | name, foundation year, city | many-to-many with Tournament, one-to-many with Player |
| Player | name, surname, date of birth, role, height | many-to-one with Team |
| Referee | name, surname, referee code | one-to-many with Match |
| Match | date, venue, home/away goals, status (SCHEDULED/PLAYED) | many-to-one with Tournament, two teams, and a referee |
| User | username, password (BCrypt), role (USER/ADMIN) | one-to-many with Comment |
| Comment | text, date | many-to-one with User and Match |
The Comment entity emerged during analysis: it wasn't in the original entity list but was required by the use cases "view comments" and "add/edit a comment on a match".
Classic layered architecture, following separation of concerns:
Browser -> Controller -> Service -> Repository -> Database
- Controller — handles HTTP requests, delegates to services, never contains business logic
- Service — business logic, validation rules, transaction boundaries (@Transactional)
- Repository — Spring Data JPA interfaces, derived queries plus custom JPQL
- Security — Spring Security filter chain, role-based access (public / user / admin), UI-level hiding combined with server-side endpoint protection
DTOs are used for all REST API responses to avoid exposing JPA entity internals and bidirectional relationship cycles during JSON serialization.
As part of the coursework, I benchmarked two fetching strategies for loading teams with their players (30 teams x 4 players):
| Strategy | Queries executed | Time |
|---|---|---|
| LAZY (naive, N+1 problem) | 31 | 218 ms |
| JOIN FETCH (targeted JPQL) | 1 | 37 ms |
JOIN FETCH was about 6x faster. I kept LAZY as the default fetch type across the codebase and used a targeted JOIN FETCH query only for the specific use case that needed it, rather than switching to FetchType.EAGER globally, which would have loaded player data even where it isn't needed.
- Create a PostgreSQL database named "offside"
- Configure src/main/resources/application.properties with your DB credentials
- Run the application:
The app runs on http://localhost:8080.
cd frontend npm install npm run dev Runs on http://localhost:5173. The production build is already bundled into src/main/resources/static/app/.
| Role | Username | Password |
|---|---|---|
| Admin | admin | admin123 |
- No optimistic locking (@Version): concurrent edits by two admins on the same entity are not detected.
- OAuth login and cloud deployment were considered as optional bonus features but not implemented, in favor of consolidating the core requirements.
Tamer Omar — Computer Engineering and AI student, Roma Tre University


