A production-grade REST API for managing strength training programs, featuring clean architecture, domain-driven design, and real business logic.
- User Management - JWT-based authentication with refresh tokens
- Training Sessions - Log workouts with exercises, sets, reps, and RPE
- 1RM Calculations - Epley, Brzycki, and RPE-based formulas
- PR Tracking - Automatic personal record detection
- Analytics - Volume tracking and progression insights
- Clean Architecture - Hexagonal design with clear separation of concerns
src/main/java/com/cleanlift/
├── domain/ # Core business logic (no dependencies)
│ ├── model/ # Entities, Value Objects, Aggregates
│ ├── service/ # Domain services (e.g., 1RM Calculator)
│ └── exception/ # Domain exceptions
├── application/ # Use cases & orchestration
│ ├── port/in/ # Input ports (use case interfaces)
│ ├── port/out/ # Output ports (repository interfaces)
│ ├── service/ # Application services
│ └── dto/ # Data Transfer Objects
├── infrastructure/ # External concerns
│ ├── adapter/
│ │ ├── persistence/ # JPA entities & repositories
│ │ └── web/ # REST controllers & security
│ └── config/ # Spring configurations
└── shared/ # Utilities & annotations
- Java 21+
- Maven 3.9+
- Docker (optional, for PostgreSQL)
# Clone the repository
git clone https://github.com/yourusername/cleanlift.git
cd cleanlift
# Run with in-memory H2 database
./mvnw spring-boot:run -Dspring-boot.run.profiles=dev# Start PostgreSQL and the API
docker-compose up -d
# Or just PostgreSQL
docker-compose up -d postgres
# Then run the app
./mvnw spring-boot:run -Dspring-boot.run.profiles=prod \
-Dspring-boot.run.arguments="--DB_HOST=localhost --DB_USERNAME=cleanlift --DB_PASSWORD=cleanlift123"Once running, access the interactive API docs:
- Swagger UI: http://localhost:8080/swagger-ui.html
- OpenAPI Spec: http://localhost:8080/api-docs
curl -X POST http://localhost:8080/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "athlete@example.com",
"password": "securepassword123",
"firstName": "John",
"lastName": "Doe"
}'curl -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "athlete@example.com",
"password": "securepassword123"
}'# Run all tests
./mvnw test
# Run unit tests only
./mvnw test -Dtest=*Test
# Run integration tests (requires Docker)
./mvnw verify -DskipUnitTests| Value Object | Description |
|---|---|
Weight |
Immutable weight in kg with lb conversion |
Reps |
Validated repetition count (0-100) |
RPE |
Rate of Perceived Exertion (6.0-10.0) |
The API supports multiple estimation formulas:
- Epley:
weight × (1 + reps/30)- Best for 4-10 reps - Brzycki:
weight × (36 / (37 - reps))- Best for 1-10 reps - RPE-based: Uses percentage tables for accurate estimates
// Example usage
Weight e1rm = OneRepMaxCalculator.epley(Weight.ofKg(100), Reps.of(5));
// Result: ~116.67 kg| Technology | Purpose |
|---|---|
| Spring Boot 3.4 | Application framework |
| Spring Security | JWT authentication |
| Spring Data JPA | Data persistence |
| PostgreSQL 16 | Production database |
| H2 | Development database |
| Flyway | Database migrations |
| MapStruct | DTO mapping |
| Lombok | Boilerplate reduction |
| OpenAPI/Swagger | API documentation |
| Testcontainers | Integration testing |
| JUnit 5 | Unit testing |
cleanlift/
├── .github/workflows/ # CI/CD pipelines
├── src/
│ ├── main/
│ │ ├── java/ # Application code
│ │ └── resources/
│ │ ├── db/migration/ # Flyway migrations
│ │ └── application*.yml # Configuration
│ └── test/ # Test code
├── docker-compose.yml # Local development
├── Dockerfile # Container build
└── pom.xml # Maven configuration
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Built with 💪 for strength athletes and developers