Agile Express is an end-to-end Agile project management system combining a Spring Boot backend with a React + Vite frontend, designed to support Scrum workflows such as backlog management, sprint planning, and task tracking.
Developed by Ahmet Atar during the OBSS CodeCamp 2025 Java Challengers internship program.
Agile Express provides a collaborative platform for Agile teams to manage projects, sprints, and tasks efficiently.
It supports role-based access control (RBAC), hybrid authentication (LDAP + Google OAuth), real-time notifications via WebSockets, and file management via MinIO.
- Project Management: Guided project creation, exclusive team assignments.
- Sprint Management: Draft → Active → Completed lifecycle with automatic draft generation.
- Task Board: Drag-and-drop task transitions between TODO → PROGRESS → REVIEW → DONE.
- Time Logging & Burndown Charts: Track and visualize sprint performance.
- Comments & Mentions: Rich-text comments with @mentions triggering notifications and emails.
- Notifications: Real-time in-app updates + email alerts.
- Authentication: LDAP + Google OAuth 2.0 with JWT (RSA256) + Refresh Tokens.
- File Uploads: MinIO S3-compatible storage with presigned download URLs.
- User Provision: New user accounts provisioned in LDAP and synchronized into PostgreSQL.
- Password Recovery: Email verification codes via Redis.
- React 19, Vite, TypeScript
- Tailwind CSS, ShadCN, Radix UI, Lucide Icons
- Redux Toolkit + RTK Query
- DND Kit for drag-and-drop boards
- SockJS + StompJS for WebSockets
- Framer Motion for animations
- Spring Boot 3.2.5 (Java 17)
- Spring Security (JWT RSA256, RBAC), Spring Data JPA, Spring Data LDAP, Spring Data Redis
- PostgreSQL 17, Redis 7, OpenLDAP
- MinIO for file storage
- Mailpit / Gmail SMTP for email delivery
- Thymeleaf for templated emails
- Maven for build automation
- Docker Compose for local environment orchestration
- Testcontainers for integration testing
agile-express/
├── backend/
│ ├── src/main/java/... # Java source code
│ ├── src/main/resources # Configuration, templates, static files
│ └── src/test # Unit tests for repositories and services
├── frontend/ # React + Vite SPA
│ ├── public/
│ └── src/ # UI components, pages, Redux store
├── docker-compose.yml # Local dev services
└── README.md
- Java 17+
- Maven 3.8+
- Node.js 20+ & npm
- Docker & Docker Compose
git clone https://github.com/CAPELLAX02/agile-express.git
cd agile-express
server:
port: ${SERVER_PORT}
spring:
application:
name: ${SPRING_APPLICATION_NAME}
config:
activate:
on-profile: env
datasource:
url: ${SPRING_DATASOURCE_URL}
username: ${SPRING_DATASOURCE_USERNAME}
password: ${SPRING_DATASOURCE_PASSWORD}
driver-class-name: ${SPRING_DATASOURCE_DRIVER_CLASS_NAME}
jpa:
database: ${SPRING_JPA_DATABASE}
database-platform: ${SPRING_JPA_DATABASE_PLATFORM}
show-sql: ${SPRING_JPA_SHOW_SQL}
open-in-view: ${SPRING_JPA_OPEN_IN_VIEW}
hibernate:
ddl-auto: ${SPRING_JPA_HIBERNATE_DDL_AUTO}
properties:
hibernate:
format_sql: ${SPRING_JPA_PROPERTIES_HIBERNATE_FORMAT_SQL}
order_updates: ${SPRING_JPA_PROPERTIES_HIBERNATE_ORDER_UPDATES}
order_inserts: ${SPRING_JPA_PROPERTIES_HIBERNATE_ORDER_INSERTS}
jdbc:
batch_size: ${SPRING_JPA_PROPERTIES_HIBERNATE_JDBC_BATCH_SIZE}
fetch_size: ${SPRING_JPA_PROPERTIES_HIBERNATE_JDBC_FETCH_SIZE}
ldap:
urls: ${SPRING_LDAP_URLS}
base: ${SPRING_LDAP_BASE}
username: ${SPRING_LDAP_USERNAME}
password: ${SPRING_LDAP_PASSWORD}
mail:
host: ${SPRING_MAIL_HOST}
port: ${SPRING_MAIL_PORT}
username: ${SPRING_MAIL_USERNAME}
password: ${SPRING_MAIL_PASSWORD}
protocol: ${SPRING_MAIL_PROTOCOL}
default-encoding: ${SPRING_MAIL_DEFAULT_ENCODING}
properties:
mail:
smtp:
auth: ${SPRING_MAIL_PROPERTIES_MAIL_SMTP_AUTH}
starttls:
required: ${SPRING_MAIL_PROPERTIES_MAIL_SMTP_STARTTLS_REQUIRED}
enable: ${SPRING_MAIL_PROPERTIES_MAIL_SMTP_STARTTLS_ENABLE}
data:
redis:
host: ${SPRING_REDIS_HOST}
port: ${SPRING_REDIS_PORT}
rsa:
public-key: classpath:certs/public.pem
private-key: ${RSA_PRIVATE_KEY}
jwt:
access-token-expiration-ms: ${JWT_ACCESS_TOKEN_EXPIRATION_MS}
refresh-token-expiration-ms: ${JWT_REFRESH_TOKEN_EXPIRATION_MS}
google:
client-id: ${GOOGLE_CLIENT_ID}
app:
frontend-base-url: ${APP_FRONTEND_BASE_URL}
cors:
allowed-origins: ${APP_CORS_ALLOWED_ORIGINS}
allowed-methods: ${APP_CORS_ALLOWED_METHODS}
allowed-headers: ${APP_CORS_ALLOWED_HEADERS}
exposed-headers: ${APP_CORS_EXPOSED_HEADERS}
allow-credentials: ${APP_CORS_ALLOW_CREDENTIALS}
ratelimit:
general:
limit: ${APP_RATELIMIT_GENERAL_LIMIT}
duration-seconds: ${APP_RATELIMIT_GENERAL_DURATION_SECONDS}
login:
limit: ${APP_RATELIMIT_LOGIN_LIMIT}
duration-seconds: ${APP_RATELIMIT_LOGIN_DURATION_SECONDS}
minio:
endpoint: ${MINIO_ENDPOINT}
access-key: ${MINIO_ACCESS_KEY}
secret-key: ${MINIO_SECRET_KEY}
bucket-name: ${MINIO_BUCKET_NAME}
Variable | Example |
---|---|
VITE_GOOGLE_CLIENT_ID | ...apps.googleusercontent.com |
docker-compose up -d
cd backend
mvn spring-boot:run
Backend will be available at http://localhost:8080.
cd frontend
npm install
npm run dev
Frontend will be available at http://localhost:5173.
Swagger UI is available at:
http://localhost:8080/swagger-ui.html
cd backend
mvn test
- Uses JUnit 5, Mockito, and Testcontainers.
Pull requests are welcome. You can open an issue first to discuss any major changes, or you can fork the repository, make the changes, and open up a pull request.