Status: ✅ Ready for review
A modern task management application built with Angular 18, Spring Boot 3.5.9, NgRx, and PostgreSQL. Features Docker containerization with Docker Compose for easy deployment and development.
- Overview
- Tech Stack
- Project Structure
- Getting Started
- Development
- Architecture
- API Documentation
- Testing
- Deployment
- Contributing
- Roadmap
Task Manager is a full-stack application for managing tasks using a Kanban board interface.
Recruiter Snapshot
- One-command launch:
docker-compose up -d(frontend, backend, Postgres) - Runtime translations: live language switch without reload (SSR friendly)
- Modern stack: Angular 18 + NgRx, Spring Boot 3.5, PostgreSQL 17, Docker
- Frontend served via Nginx; backend packaged with multi-stage builds
- Clean, layered architecture and standardized REST responses
Key Features:
- ✅ Task CRUD operations (Create, Read, Update, Delete)
- ✅ Kanban board view with drag-and-drop support
- ✅ Task status management (TODO, IN_PROGRESS, DONE)
- ✅ User context management via header-based authentication
- ✅ Real-time toast notifications
- ✅ Responsive design with Tailwind CSS
- ✅ Runtime language switching with persisted preference
- ✅ Server-Side Rendering (SSR) support
- ✅ Docker containerization with Docker Compose
- ✅ RESTful API with standardized responses
- Framework: Spring Boot 3.5.9
- Java: 17
- Database: PostgreSQL 17
- ORM: Spring Data JPA
- Mapping: MapStruct 1.6.3
- Build Tool: Maven 3.9+
- Container: Docker with multi-stage build
- Other: Lombok, Bean Validation, Spring Boot DevTools
- Framework: Angular 18.2
- State Management: NgRx 18.1 (Store, Effects)
- Styling: Tailwind CSS 3.4
- SSR: Angular SSR (Server-Side Rendering)
- Build Tool: Angular CLI 18.2+
- Container: Docker with Nginx
- Other: Angular CDK
backend/
├── src/
│ ├── main/
│ │ ├── java/com/taskmanager/
│ │ │ ├── common/ # Shared utilities
│ │ │ │ ├── exception/ # Global exception handling
│ │ │ │ │ ├── GlobalExceptionHandler.java
│ │ │ │ │ └── ResourceNotFoundException.java
│ │ │ │ └── response/ # API response models
│ │ │ │ ├── ApiResponse.java
│ │ │ │ ├── ApiError.java
│ │ │ │ ├── ApiMessage.java
│ │ │ │ └── MessageType.java
│ │ │ ├── config/ # Configuration classes
│ │ │ │ └── CorsConfig.java
│ │ │ ├── task/ # Task feature module
│ │ │ │ ├── api/ # REST controllers
│ │ │ │ │ └── TaskController.java
│ │ │ │ ├── application/ # Service layer
│ │ │ │ │ └── TaskService.java
│ │ │ │ ├── domain/ # Domain entities & repositories
│ │ │ │ │ ├── Task.java
│ │ │ │ │ ├── TaskRepository.java
│ │ │ │ │ └── TaskStatus.java
│ │ │ │ ├── dto/ # Data Transfer Objects
│ │ │ │ │ ├── TaskResponse.java
│ │ │ │ │ ├── TaskUpsertRequest.java
│ │ │ │ │ └── TaskStatusUpdateRequest.java
│ │ │ │ └── mapper/ # MapStruct mappers
│ │ │ │ └── TaskMapper.java
│ │ │ └── WorkflowManagerApplication.java
│ │ └── resources/
│ │ ├── application.properties
│ │ ├── application-dev.properties
│ │ └── application-docker.properties
│ └── test/ # Test classes
├── dockerfile # Docker configuration
├── pom.xml # Maven configuration
└── logs/ # Application logs
Best Practices:
- ✅ Layered architecture (API → Application → Domain)
- ✅ DTOs for request/response separation
- ✅ MapStruct for type-safe mapping
- ✅ Global exception handling with standardized error responses
- ✅ CORS configuration for frontend integration
- ✅ Environment-specific configuration (dev, docker, production)
- ✅ Health checks for container orchestration
- ✅ Security best practices (non-root user, minimal base images)
frontend/
├── src/
│ ├── app/
│ │ ├── core/ # Singleton services, interceptors
│ │ │ ├── api/ # API services
│ │ │ │ └── task-api.service.ts
│ │ │ ├── interceptor/ # HTTP interceptors
│ │ │ │ └── user-id.interceptor.ts
│ │ │ ├── models/ # Core domain models
│ │ │ │ ├── task.ts
│ │ │ │ ├── api-response.ts
│ │ │ │ └── toast-message.ts
│ │ │ ├── services/ # Core services
│ │ │ │ └── toast.service.ts
│ │ │ └── user/ # User context
│ │ │ └── user-context.service.ts
│ │ ├── features/ # Feature modules
│ │ │ └── tasks/
│ │ │ ├── components/ # Feature components
│ │ │ │ ├── task-card/
│ │ │ │ ├── task-form/
│ │ │ │ └── task-lane/
│ │ │ ├── pages/ # Page/container components
│ │ │ │ └── tasks-board/
│ │ │ └── store/ # NgRx store
│ │ │ ├── task.actions.ts
│ │ │ ├── task.effects.ts
│ │ │ ├── task.reducer.ts
│ │ │ ├── task.selectors.ts
│ │ │ └── task.state.ts
│ │ ├── shared/ # Shared components, directives, pipes
│ │ │ ├── components/
│ │ │ │ └── toast/
│ │ │ └── utils/
│ │ │ └── task-util.ts
│ │ ├── app.config.ts # Application configuration
│ │ ├── app.config.server.ts # SSR configuration
│ │ └── app.routes.ts # Routing configuration
│ ├── environments/
│ │ ├── environment.ts # Development environment
│ │ └── environment.prod.ts # Production environment
│ ├── main.ts # Application bootstrap
│ ├── main.server.ts # SSR bootstrap
│ └── styles.css # Global styles
├── dockerfile # Docker configuration
├── angular.json # Angular configuration
├── tailwind.config.js # Tailwind CSS configuration
└── package.json # Dependencies
Best Practices:
- ✅ Feature-based architecture
- ✅ Core vs Shared separation
- ✅ NgRx store per feature (actions, effects, reducers, selectors)
- ✅ Standalone components (Angular 18+)
- ✅ Server-Side Rendering (SSR) support
- ✅ HTTP interceptors for request/response handling
- ✅ Type-safe models and API responses
- ✅ Responsive design with Tailwind CSS
Option 1: Local Development (without Docker)
- Backend:
- JDK 17 or higher
- Maven 3.9+
- PostgreSQL 17
- Frontend:
- Node.js 18+ and npm
- Angular CLI 18+ (
npm install -g @angular/cli)
Option 2: Docker Development
- Docker
- Docker Compose
The easiest way to run the entire application:
# Start all services (backend, frontend, database)
docker-compose up -d
# View logs
docker-compose logs -f
# Stop all services
docker-compose downServices:
- Frontend:
http://localhost:4200 - Backend API:
http://localhost:8080 - PostgreSQL:
localhost:5432
Database Configuration:
- Database name:
task_manager - Username:
postgres - Password:
postgres - Port:
5432
Note: On first run, Docker will build the images. Subsequent runs will be faster. All services are connected via a Docker network (task-manager-network) and have health checks configured for proper startup orchestration.
The backend is automatically configured when using docker-compose up. Database connection is pre-configured.
-
Configure Database
# Update backend/src/main/resources/application.properties spring.datasource.url=jdbc:postgresql://localhost:5432/task_manager spring.datasource.username=postgres spring.datasource.password=postgres
-
Start PostgreSQL (if not using Docker)
# Using Docker docker run -d --name postgres-db \ -e POSTGRES_DB=task_manager \ -e POSTGRES_USER=postgres \ -e POSTGRES_PASSWORD=postgres \ -p 5432:5432 \ postgres:17-alpine -
Run Backend
cd backend ./mvnw spring-boot:run # Or on Windows: mvnw.cmd spring-boot:run
Backend will start on
http://localhost:8080(default)
Environment Profiles:
- Default:
application.properties - Development:
application-dev.properties - Docker:
application-docker.properties
The frontend is automatically built and served when using docker-compose up. It uses Nginx to serve the production build.
-
Install Dependencies
cd frontend npm install -
Configure Environment
// Update frontend/src/environments/environment.ts export const environment = { apiUrl: 'http://localhost:8080/api' };
-
Run Frontend
npm start # Or: ng serveFrontend will start on
http://localhost:4200(default)
Note: When running locally, the frontend communicates with the backend API. Ensure the backend is running or use Docker Compose to run both services together.
Start development environment:
docker-compose up -dView logs:
# All services
docker-compose logs -f
# Specific service
docker-compose logs -f backend
docker-compose logs -f frontend
docker-compose logs -f postgresRestart a service:
docker-compose restart backendRebuild after code changes:
docker-compose up -d --buildRunning Tests:
cd backend
./mvnw testBuild:
./mvnw clean packageRun with Maven:
./mvnw spring-boot:runView Logs:
- Local: Console output
- Docker:
docker-compose logs -f backendor check./logs/workflow-manager.log
Health Check:
- Local:
http://localhost:8080/actuator/health - Docker: Automatically checked by docker-compose healthcheck
Code Style:
- Follow Spring Boot best practices
- Use Lombok for reducing boilerplate
- MapStruct for DTO mapping
Running Tests:
cd frontend
npm testBuild:
# Production build
npm run build
# Development build with watch mode
npm run watchDevelopment Server:
npm start
# Or: ng serveLinting:
ng lintCode Coverage:
- Coverage reports generated in
coverage/directory - View
coverage/task-manager-angular18-ngrx/index.htmlin browser
Code Style:
- Follow Angular Style Guide
- ESLint configured with
angular-eslint - Use standalone components
- Feature-based architecture with NgRx
Layered Architecture Pattern:
-
API Layer (
api/)- REST controllers
- Request validation
- Response formatting
-
Application Layer (
application/)- Business logic
- Transaction management
- Orchestration
-
Domain Layer (
domain/)- Entity models
- Repository interfaces
- Domain enums
-
DTO Layer (
dto/)- Request DTOs
- Response DTOs
- Validation annotations
Additional:
- Global exception handler (
GlobalExceptionHandler) - CORS configuration (
CorsConfig) - Standardized API responses (
ApiResponse<T>)
Feature-Based Architecture:
- Each feature is self-contained with components, pages, and store
- Features communicate through NgRx store or shared services
NgRx Pattern:
- Actions: Define events/dispatches
- Effects: Handle side effects (API calls)
- Reducers: Pure functions for state updates
- Selectors: Memoized state queries
Core Services:
- API services (feature-agnostic HTTP calls)
- Interceptors (auth, headers, etc.)
- User context service
Shared:
- Reusable components (toast, buttons, etc.)
- Directives and pipes
- Utilities
Development:
http://localhost:8080/api
Docker:
http://localhost:8080/api
The API uses header-based authentication for user identification:
- Header:
x-user-id - Type: String (user identifier)
- Required: Yes (for all task-related endpoints)
All API requests must include the x-user-id header to identify the current user. The backend validates this header to ensure proper user context for all operations.
Example Request:
GET /api/tasks HTTP/1.1
Host: localhost:8080
x-user-id: user123Example Response:
{
"messageType": "success",
"data": [
{
"id": 1,
"title": "Sample Task",
"description": "Task description",
"status": "TODO",
"userId": "user123",
"createdAt": "2024-01-01T00:00:00",
"updatedAt": "2024-01-01T00:00:00"
}
],
"message":""
}Base Path: /api/tasks
All endpoints require the x-user-id header.
| Method | Endpoint | Description |
|---|---|---|
GET |
/tasks |
Get all tasks for the authenticated user |
POST |
/tasks |
Create a new task |
GET |
/tasks/{id} |
Get a specific task by ID |
PUT |
/tasks/{id} |
Update an existing task |
PATCH |
/tasks/{id}/status |
Update only the task status |
DELETE |
/tasks/{id} |
Delete a task |
Task Status Values:
TODOIN_PROGRESSDONE
Example Requests:
Create Task:
POST /api/tasks HTTP/1.1
Host: localhost:8080
x-user-id: user123
Content-Type: application/json
{
"title": "New Task",
"description": "Task description",
"status": "TODO"
}Update Task Status:
PATCH /api/tasks/1/status HTTP/1.1
Host: localhost:8080
x-user-id: user123
Content-Type: application/json
{
"status": "IN_PROGRESS"
}Unit Tests:
cd backend
./mvnw testTest Structure:
- Unit tests for services, repositories, and controllers
- Test files located in
src/test/java/
Test Coverage:
- Use Maven Surefire Plugin for test execution
- Consider JaCoCo for coverage reporting (add as needed)
Unit Tests:
cd frontend
npm testTest Structure:
- Component tests with Jasmine and Karma
- Service tests
- Store tests (actions, reducers, selectors, effects)
- Test files:
*.spec.ts - Coverage reports:
coverage/task-manager-angular18-ngrx/
Test Coverage:
- Karma coverage plugin configured
- View coverage report: Open
coverage/task-manager-angular18-ngrx/index.htmlin browser
Backend:
cd backend
docker build -t backend:latest .Frontend:
cd frontend
docker build -t frontend:latest .# Build and start all services
docker-compose up -d --build
# View logs
docker-compose logs -f
# Stop services
docker-compose down
# Stop and remove volumes (clean reset)
docker-compose down -vLocal Build:
cd backend
./mvnw clean package -DskipTestsRun JAR:
java -jar target/workflow-manager-0.0.1-SNAPSHOT.jarDocker:
- Multi-stage build (Maven build → JDK runtime)
- Includes health checks (Spring Boot Actuator)
- Exposes port 8080
- Logs directory mounted to
./logs
Environment Variables:
SPRING_DATASOURCE_URL: Database connection URLSPRING_DATASOURCE_USERNAME: Database usernameSPRING_DATASOURCE_PASSWORD: Database passwordSPRING_PROFILES_ACTIVE: Active Spring profile (docker/dev)CORS_ALLOWED_ORIGINS: Allowed CORS origins (comma-separated)SERVER_PORT: Server port (default: 8080)
Local Build:
cd frontend
npm run buildProduction Build Output:
- Output directory:
dist/task-manager-angular18-ngrx/browser/ - Includes SSR build in
dist/task-manager-angular18-ngrx/server/
Docker:
- Multi-stage build (Node build → Nginx serve)
- Uses Nginx Alpine for lightweight container (~25MB)
- Serves static files from
/usr/share/nginx/html/ - Exposes port 80 (mapped to 4200 in docker-compose)
- Production-optimized build included
Environment Configuration:
- Development:
src/environments/environment.ts - Production:
src/environments/environment.prod.ts
- [Fork the repository]
- [Create a feature branch]
- [Commit your changes]
- [Push to the branch]
- [Create a Pull Request]
Coding Standards:
- Follow Spring Boot best practices for backend
- Follow Angular Style Guide for frontend
- Write tests for new features
- Update documentation
- Add authentication/authorization (using
x-user-idheader) - Runtime i18n with language switcher
- Complete frontend/backend unit tests
- Add E2E Tests
- Add user management
- Enhance task filtering and search
- File attachments
- Task comments
- Activity history
- Multi-user collaboration
- Team workspaces
- Analytics and reporting
This project is licensed under the MIT License.
Note: This README is kept current; reach out if you need a live demo link.