Case Study
A REST API for tracking job applications
A REST API that models the full lifecycle of my own job applications – from "applied" to "accepted". Deliberately built as a practice project during my job search to sharpen API design, containerisation and automated testing.
Tech stack
- Backend: PHP 8.3, Symfony 7, Doctrine ORM
- Database: MySQL 8
- Infrastructure: Docker & Docker Compose (Nginx, PHP-FPM, MySQL as separate containers)
- Tests: PHPUnit – unit and functional tests (15 tests)
Challenges & solutions
1. Enforcing valid status transitions
An application must not jump from any status to any other (e.g. not directly from "applied" to "accepted"). The transition logic lives as its own business rule in the domain code rather than scattered across the controller, with a dedicated PATCH endpoint for status changes.
2. Clean REST design instead of raw CRUD endpoints
Endpoints return consistent HTTP status codes (200, 201, 204, 404, 422) and structured validation errors, so a client can reliably distinguish "invalid input" from "not found".
3. Test-driven from the start
15 tests cover both the status logic at the unit level and the HTTP endpoints functionally – a deliberate exercise in writing tests alongside functionality instead of afterwards.
4. A reproducible environment with Docker
Nginx, PHP-FPM and MySQL run as separate containers via Docker Compose. A single "docker compose up -d --build" plus migrations is enough to run the application identically anywhere.
My role
Sole developer: API design, domain logic, database modelling, tests and the Docker setup are entirely my work – a deliberate practice project for backend and DevOps skills.
Result
A working, fully containerised REST API with a clean status lifecycle, consistent HTTP responses and 15 passing tests – a compact demonstration of API design, testing discipline and Docker knowledge.