Small portfolio project demonstrating an API-first workflow with OpenAPI, Spring Boot, and Angular.
The goal is not to build a full task management product. The goal is to show how one OpenAPI contract can drive both backend and frontend types, routes, request models, response models, validation constraints, and tests.
- OpenAPI contract as the source of truth
- Generated Spring Boot interfaces and DTOs
- Generated Angular API client
- Hand-written business logic behind generated backend contracts
- Thin Angular services wrapping the generated client
- Contract-driven validation and error responses
- Focused tests that prove the generated API boundary works
openapi/src/main/resources/task-board-api.json
|
| generate-sources
v
task-board-service/target/generated-sources/openapi
|
v
Spring controllers implement generated API interfaces
|
v
ProjectService / TaskService / in-memory repositories
openapi/src/main/resources/task-board-api.json
|
| npm run openapi:regen
v
task-board-app/src/generated-api
|
v
ProjectService / TaskService Angular wrappers
|
v
Signal-based task board UI
Generated code is deliberately not committed. It is regenerated during backend builds and frontend build/test/start scripts, so contract changes are reflected immediately on both sides.
The API models a minimal project/task board:
- create and list projects
- create and list tasks within a project
- reject invalid request bodies
- return a clear error when tasks are requested for a missing project
Persistence is intentionally in-memory. Database setup, authentication, authorization, pagination, and deployment are outside the scope of this showcase.
openapi/
src/main/resources/task-board-api.json # source contract
src/test/resources/task-board-api.http # runnable HTTP examples
task-board-service/
src/main/java/... # Spring Boot implementation
src/test/java/... # API and service tests
task-board-app/
src/app/... # Angular UI and service wrappers
openapi-config.json # Angular client generation config
cd task-board-service
./mvnw spring-boot:run
The service runs on:
http://localhost:8080
Swagger UI is available at:
http://localhost:8080/swagger-ui.html
cd task-board-app
npm install
npm start
The Angular app runs on:
http://localhost:4200
The frontend uses proxy.conf.json to forward /projects requests to the Spring Boot service.
Backend:
cd task-board-service
./mvnw test
Frontend:
cd task-board-app
npm test -- --watch=false --progress=false
Frontend build:
cd task-board-app
npm run build
Backend-generated sources are created by Maven:
cd task-board-service
./mvnw generate-sources
Frontend-generated sources are created by OpenAPI Generator:
cd task-board-app
npm run openapi:regen
The frontend also regenerates automatically before npm start, npm test, and npm run build.
Use:
openapi/src/test/resources/task-board-api.http
It includes examples for:
- listing projects
- creating a project
- listing tasks for a created project
- creating a task
- validation failure
- missing project failure
This project intentionally keeps the domain small. The interesting part is the workflow:
- Change the OpenAPI contract.
- Regenerate backend and frontend code.
- Implement business behavior behind generated interfaces.
- Consume generated client types through thin Angular services.
- Verify the contract boundary with focused tests.
The app avoids a large frontend state framework. Angular signals and a small local state model are enough for this showcase