Index: backend/Dockerfile
===================================================================
--- backend/Dockerfile	(revision 545738f221bcda7888ec3b35279f55d0f80c4faa)
+++ backend/Dockerfile	(revision 545738f221bcda7888ec3b35279f55d0f80c4faa)
@@ -0,0 +1,11 @@
+FROM maven:3.9-eclipse-temurin-21 AS build
+WORKDIR /app
+COPY pom.xml .
+RUN mvn dependency:go-offline -q
+COPY src ./src
+RUN mvn package -DskipTests -q
+
+FROM eclipse-temurin:21-jre
+WORKDIR /app
+COPY --from=build /app/target/backend-0.0.1-SNAPSHOT.jar app.jar
+ENTRYPOINT ["java", "-jar", "app.jar"]
Index: backend/src/main/java/com/trekr/backend/config/SecurityConfig.java
===================================================================
--- backend/src/main/java/com/trekr/backend/config/SecurityConfig.java	(revision 194c01621e96510fb6f238b2098a64b3663ec780)
+++ backend/src/main/java/com/trekr/backend/config/SecurityConfig.java	(revision 545738f221bcda7888ec3b35279f55d0f80c4faa)
@@ -49,5 +49,7 @@
         config.setAllowedOrigins(List.of(
                 "http://localhost:5173",
-                "http://127.0.0.1:5173"));
+                "http://127.0.0.1:5173",
+                "http://localhost:3000",
+                "http://127.0.0.1:3000"));
         config.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
         config.setAllowedHeaders(List.of("Authorization", "Content-Type", "Accept", "Origin", "X-Requested-With"));
Index: backend/src/main/java/com/trekr/backend/controller/CustomTrackingController.java
===================================================================
--- backend/src/main/java/com/trekr/backend/controller/CustomTrackingController.java	(revision 194c01621e96510fb6f238b2098a64b3663ec780)
+++ backend/src/main/java/com/trekr/backend/controller/CustomTrackingController.java	(revision 545738f221bcda7888ec3b35279f55d0f80c4faa)
@@ -9,4 +9,5 @@
 import com.trekr.backend.dto.discipline.UpdateTaskFinishedRequest;
 import com.trekr.backend.dto.discipline.UpdateTaskRequest;
+import com.trekr.backend.dto.discipline.UpdateTaskStatusRequest;
 import com.trekr.backend.security.UserPrincipal;
 import com.trekr.backend.service.CustomTrackingService;
@@ -79,4 +80,14 @@
     }
 
+    @PatchMapping("/{customTrackingId}/tasks/{taskId}/status")
+    public TaskDto updateTaskStatus(
+            @PathVariable Long customTrackingId,
+            @PathVariable Long taskId,
+            @RequestBody UpdateTaskStatusRequest request,
+            Authentication authentication) {
+        UserPrincipal principal = (UserPrincipal) authentication.getPrincipal();
+        return customTrackingService.updateCustomCategoryTaskStatus(principal.getUserId(), customTrackingId, taskId, request);
+    }
+
     @DeleteMapping("/{customTrackingId}/tasks/{taskId}")
     @ResponseStatus(HttpStatus.NO_CONTENT)
Index: backend/src/main/java/com/trekr/backend/dto/discipline/CreateTaskRequest.java
===================================================================
--- backend/src/main/java/com/trekr/backend/dto/discipline/CreateTaskRequest.java	(revision 194c01621e96510fb6f238b2098a64b3663ec780)
+++ backend/src/main/java/com/trekr/backend/dto/discipline/CreateTaskRequest.java	(revision 545738f221bcda7888ec3b35279f55d0f80c4faa)
@@ -2,4 +2,6 @@
 
 import jakarta.validation.constraints.NotBlank;
+
+import java.time.LocalDate;
 
 public class CreateTaskRequest {
@@ -8,14 +10,21 @@
     private String name;
 
+    private String description;
+    private LocalDate dueDate;
+    private String priority;
+
     public CreateTaskRequest() {
     }
 
-    public String getName() {
-        return name;
-    }
+    public String getName() { return name; }
+    public void setName(String name) { this.name = name; }
 
-    public void setName(String name) {
-        this.name = name;
-    }
+    public String getDescription() { return description; }
+    public void setDescription(String description) { this.description = description; }
+
+    public LocalDate getDueDate() { return dueDate; }
+    public void setDueDate(LocalDate dueDate) { this.dueDate = dueDate; }
+
+    public String getPriority() { return priority; }
+    public void setPriority(String priority) { this.priority = priority; }
 }
-
Index: backend/src/main/java/com/trekr/backend/dto/discipline/TaskDto.java
===================================================================
--- backend/src/main/java/com/trekr/backend/dto/discipline/TaskDto.java	(revision 194c01621e96510fb6f238b2098a64b3663ec780)
+++ backend/src/main/java/com/trekr/backend/dto/discipline/TaskDto.java	(revision 545738f221bcda7888ec3b35279f55d0f80c4faa)
@@ -1,5 +1,16 @@
 package com.trekr.backend.dto.discipline;
 
-public record TaskDto(Long taskId, String name, boolean isFinished) {
+import com.trekr.backend.entity.discipline.TaskStatus;
+
+import java.time.LocalDate;
+
+public record TaskDto(
+        Long taskId,
+        String name,
+        boolean isFinished,
+        TaskStatus status,
+        String description,
+        LocalDate dueDate,
+        String priority
+) {
 }
-
Index: backend/src/main/java/com/trekr/backend/dto/discipline/UpdateTaskRequest.java
===================================================================
--- backend/src/main/java/com/trekr/backend/dto/discipline/UpdateTaskRequest.java	(revision 194c01621e96510fb6f238b2098a64b3663ec780)
+++ backend/src/main/java/com/trekr/backend/dto/discipline/UpdateTaskRequest.java	(revision 545738f221bcda7888ec3b35279f55d0f80c4faa)
@@ -1,5 +1,8 @@
 package com.trekr.backend.dto.discipline;
 
+import com.trekr.backend.entity.discipline.TaskStatus;
 import jakarta.validation.constraints.NotBlank;
+
+import java.time.LocalDate;
 
 public class UpdateTaskRequest {
@@ -8,14 +11,25 @@
     private String name;
 
+    private String description;
+    private LocalDate dueDate;
+    private String priority;
+    private TaskStatus status;
+
     public UpdateTaskRequest() {
     }
 
-    public String getName() {
-        return name;
-    }
+    public String getName() { return name; }
+    public void setName(String name) { this.name = name; }
 
-    public void setName(String name) {
-        this.name = name;
-    }
+    public String getDescription() { return description; }
+    public void setDescription(String description) { this.description = description; }
+
+    public LocalDate getDueDate() { return dueDate; }
+    public void setDueDate(LocalDate dueDate) { this.dueDate = dueDate; }
+
+    public String getPriority() { return priority; }
+    public void setPriority(String priority) { this.priority = priority; }
+
+    public TaskStatus getStatus() { return status; }
+    public void setStatus(TaskStatus status) { this.status = status; }
 }
-
Index: backend/src/main/java/com/trekr/backend/entity/discipline/Task.java
===================================================================
--- backend/src/main/java/com/trekr/backend/entity/discipline/Task.java	(revision 194c01621e96510fb6f238b2098a64b3663ec780)
+++ backend/src/main/java/com/trekr/backend/entity/discipline/Task.java	(revision 545738f221bcda7888ec3b35279f55d0f80c4faa)
@@ -3,4 +3,6 @@
 import jakarta.persistence.Column;
 import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
 import jakarta.persistence.FetchType;
 import jakarta.persistence.GeneratedValue;
@@ -10,4 +12,6 @@
 import jakarta.persistence.ManyToOne;
 import jakarta.persistence.Table;
+
+import java.time.LocalDate;
 
 @Entity
@@ -23,6 +27,16 @@
     private String name;
 
-    @Column(name = "is_finished", nullable = false)
-    private boolean finished;
+    @Enumerated(EnumType.STRING)
+    @Column(name = "status", nullable = false)
+    private TaskStatus status = TaskStatus.NOT_STARTED;
+
+    @Column(name = "description")
+    private String description;
+
+    @Column(name = "due_date")
+    private LocalDate dueDate;
+
+    @Column(name = "priority")
+    private String priority;
 
     @ManyToOne(fetch = FetchType.LAZY)
@@ -37,40 +51,31 @@
     }
 
-    public Long getTaskId() {
-        return taskId;
+    public Long getTaskId() { return taskId; }
+    public void setTaskId(Long taskId) { this.taskId = taskId; }
+
+    public String getName() { return name; }
+    public void setName(String name) { this.name = name; }
+
+    public TaskStatus getStatus() { return status; }
+    public void setStatus(TaskStatus status) { this.status = status; }
+
+    public boolean isFinished() { return TaskStatus.FINISHED == status; }
+    public void setFinished(boolean finished) {
+        this.status = finished ? TaskStatus.FINISHED : TaskStatus.NOT_STARTED;
     }
 
-    public void setTaskId(Long taskId) {
-        this.taskId = taskId;
-    }
+    public String getDescription() { return description; }
+    public void setDescription(String description) { this.description = description; }
 
-    public String getName() {
-        return name;
-    }
+    public LocalDate getDueDate() { return dueDate; }
+    public void setDueDate(LocalDate dueDate) { this.dueDate = dueDate; }
 
-    public void setName(String name) {
-        this.name = name;
-    }
+    public String getPriority() { return priority; }
+    public void setPriority(String priority) { this.priority = priority; }
 
-    public boolean isFinished() {
-        return finished;
-    }
+    public DisciplineUser getDisciplineUser() { return disciplineUser; }
+    public void setDisciplineUser(DisciplineUser disciplineUser) { this.disciplineUser = disciplineUser; }
 
-    public void setFinished(boolean finished) {
-        this.finished = finished;
-    }
-
-    public DisciplineUser getDisciplineUser() {
-        return disciplineUser;
-    }
-
-    public void setDisciplineUser(DisciplineUser disciplineUser) {
-        this.disciplineUser = disciplineUser;
-    }
-
-    public CustomTrackingCategory getCustomTrackingCategory() {
-        return customTrackingCategory;
-    }
-
+    public CustomTrackingCategory getCustomTrackingCategory() { return customTrackingCategory; }
     public void setCustomTrackingCategory(CustomTrackingCategory customTrackingCategory) {
         this.customTrackingCategory = customTrackingCategory;
Index: backend/src/main/java/com/trekr/backend/repository/TaskRepository.java
===================================================================
--- backend/src/main/java/com/trekr/backend/repository/TaskRepository.java	(revision 194c01621e96510fb6f238b2098a64b3663ec780)
+++ backend/src/main/java/com/trekr/backend/repository/TaskRepository.java	(revision 545738f221bcda7888ec3b35279f55d0f80c4faa)
@@ -2,4 +2,5 @@
 
 import com.trekr.backend.entity.discipline.Task;
+import com.trekr.backend.entity.discipline.TaskStatus;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
@@ -19,7 +20,7 @@
     long countByDisciplineUser_UserId(Long userId);
 
-    long countByDisciplineUser_UserIdAndFinishedTrue(Long userId);
+    long countByDisciplineUser_UserIdAndStatus(Long userId, TaskStatus status);
 
-    List<Task> findByDisciplineUser_UserIdAndFinishedTrue(Long userId);
+    List<Task> findByDisciplineUser_UserIdAndStatus(Long userId, TaskStatus status);
 
     List<Task> findByCustomTrackingCategory_CustomTrackingIdAndCustomTrackingCategory_User_UserIdOrderByTaskIdDesc(
@@ -30,6 +31,5 @@
 
     @Modifying
-    @Query("update Task t set t.finished = false where t.disciplineUser.userId = :userId")
-    int resetFinishedForUser(@Param("userId") Long userId);
+    @Query("update Task t set t.status = :status where t.disciplineUser.userId = :userId")
+    int resetStatusForUser(@Param("userId") Long userId, @Param("status") TaskStatus status);
 }
-
Index: backend/src/main/java/com/trekr/backend/service/CustomTrackingService.java
===================================================================
--- backend/src/main/java/com/trekr/backend/service/CustomTrackingService.java	(revision 194c01621e96510fb6f238b2098a64b3663ec780)
+++ backend/src/main/java/com/trekr/backend/service/CustomTrackingService.java	(revision 545738f221bcda7888ec3b35279f55d0f80c4faa)
@@ -8,4 +8,6 @@
 import com.trekr.backend.dto.discipline.TasksResponse;
 import com.trekr.backend.dto.discipline.UpdateTaskFinishedRequest;
+import com.trekr.backend.dto.discipline.UpdateTaskStatusRequest;
+import com.trekr.backend.entity.discipline.TaskStatus;
 import com.trekr.backend.dto.discipline.UpdateTaskRequest;
 import com.trekr.backend.entity.User;
@@ -81,5 +83,5 @@
                         customTrackingId, userId)
                 .stream()
-                .map(t -> new TaskDto(t.getTaskId(), t.getName(), t.isFinished()))
+                .map(t -> new TaskDto(t.getTaskId(), t.getName(), t.isFinished(), t.getStatus(), t.getDescription(), t.getDueDate(), t.getPriority()))
                 .toList();
 
@@ -101,10 +103,13 @@
         Task task = new Task();
         task.setName(name.trim());
-        task.setFinished(false);
+        task.setStatus(TaskStatus.NOT_STARTED);
+        task.setDescription(request.getDescription());
+        task.setDueDate(request.getDueDate());
+        task.setPriority(request.getPriority());
         task.setDisciplineUser(null);
         task.setCustomTrackingCategory(category);
 
         Task saved = taskRepository.save(task);
-        return new TaskDto(saved.getTaskId(), saved.getName(), saved.isFinished());
+        return new TaskDto(saved.getTaskId(), saved.getName(), saved.isFinished(), saved.getStatus(), saved.getDescription(), saved.getDueDate(), saved.getPriority());
     }
 
@@ -127,6 +132,12 @@
 
         task.setName(name.trim());
-        Task saved = taskRepository.save(task);
-        return new TaskDto(saved.getTaskId(), saved.getName(), saved.isFinished());
+        task.setDescription(request.getDescription());
+        task.setDueDate(request.getDueDate());
+        task.setPriority(request.getPriority());
+        if (request.getStatus() != null) {
+            task.setStatus(request.getStatus());
+        }
+        Task saved = taskRepository.save(task);
+        return new TaskDto(saved.getTaskId(), saved.getName(), saved.isFinished(), saved.getStatus(), saved.getDescription(), saved.getDueDate(), saved.getPriority());
     }
 
@@ -151,5 +162,27 @@
         task.setFinished(finished);
         Task saved = taskRepository.save(task);
-        return new TaskDto(saved.getTaskId(), saved.getName(), saved.isFinished());
+        return new TaskDto(saved.getTaskId(), saved.getName(), saved.isFinished(), saved.getStatus(), saved.getDescription(), saved.getDueDate(), saved.getPriority());
+    }
+
+    @Transactional
+    public TaskDto updateCustomCategoryTaskStatus(Long userId, Long customTrackingId, Long taskId,
+                                                  UpdateTaskStatusRequest request) {
+        Task task = taskRepository.findById(taskId)
+                .orElseThrow(() -> new RuntimeException("Task not found"));
+
+        if (task.getCustomTrackingCategory() == null
+                || !customTrackingId.equals(task.getCustomTrackingCategory().getCustomTrackingId())
+                || task.getCustomTrackingCategory().getUser() == null
+                || !userId.equals(task.getCustomTrackingCategory().getUser().getUserId())) {
+            throw new RuntimeException("Task not found");
+        }
+
+        if (request.getStatus() == null) {
+            throw new RuntimeException("status is required");
+        }
+
+        task.setStatus(request.getStatus());
+        Task saved = taskRepository.save(task);
+        return new TaskDto(saved.getTaskId(), saved.getName(), saved.isFinished(), saved.getStatus(), saved.getDescription(), saved.getDueDate(), saved.getPriority());
     }
 
Index: backend/src/main/java/com/trekr/backend/service/DisciplineService.java
===================================================================
--- backend/src/main/java/com/trekr/backend/service/DisciplineService.java	(revision 194c01621e96510fb6f238b2098a64b3663ec780)
+++ backend/src/main/java/com/trekr/backend/service/DisciplineService.java	(revision 545738f221bcda7888ec3b35279f55d0f80c4faa)
@@ -14,4 +14,5 @@
 import com.trekr.backend.entity.discipline.Task;
 import com.trekr.backend.entity.discipline.TaskDailyCompletion;
+import com.trekr.backend.entity.discipline.TaskStatus;
 import com.trekr.backend.entity.discipline.TaskDailyCompletionId;
 import com.trekr.backend.repository.DailyCompletionRepository;
@@ -81,5 +82,5 @@
 
         List<TaskDto> tasks = result.getContent().stream()
-                .map(t -> new TaskDto(t.getTaskId(), t.getName(), t.isFinished()))
+                .map(t -> new TaskDto(t.getTaskId(), t.getName(), t.isFinished(), t.getStatus(), t.getDescription(), t.getDueDate(), t.getPriority()))
                 .toList();
 
@@ -107,5 +108,5 @@
 
         Task saved = taskRepository.save(task);
-        return new TaskDto(saved.getTaskId(), saved.getName(), saved.isFinished());
+        return new TaskDto(saved.getTaskId(), saved.getName(), saved.isFinished(), saved.getStatus(), saved.getDescription(), saved.getDueDate(), saved.getPriority());
     }
 
@@ -126,5 +127,5 @@
         task.setName(name.trim());
         Task saved = taskRepository.save(task);
-        return new TaskDto(saved.getTaskId(), saved.getName(), saved.isFinished());
+        return new TaskDto(saved.getTaskId(), saved.getName(), saved.isFinished(), saved.getStatus(), saved.getDescription(), saved.getDueDate(), saved.getPriority());
     }
 
@@ -145,5 +146,5 @@
         task.setFinished(finished);
         Task saved = taskRepository.save(task);
-        return new TaskDto(saved.getTaskId(), saved.getName(), saved.isFinished());
+        return new TaskDto(saved.getTaskId(), saved.getName(), saved.isFinished(), saved.getStatus(), saved.getDescription(), saved.getDueDate(), saved.getPriority());
     }
 
@@ -187,5 +188,5 @@
 
         long total = taskRepository.countByDisciplineUser_UserId(userId);
-        long finished = taskRepository.countByDisciplineUser_UserIdAndFinishedTrue(userId);
+        long finished = taskRepository.countByDisciplineUser_UserIdAndStatus(userId, TaskStatus.FINISHED);
 
         BigDecimal percent;
@@ -210,5 +211,5 @@
         // (not strictly required for now, but matches schema and enables future analytics)
         if (finished > 0) {
-            List<TaskDailyCompletion> links = taskRepository.findByDisciplineUser_UserIdAndFinishedTrue(userId)
+            List<TaskDailyCompletion> links = taskRepository.findByDisciplineUser_UserIdAndStatus(userId, TaskStatus.FINISHED)
                     .stream()
                     .map(t -> {
@@ -224,5 +225,5 @@
 
         // Reset all tasks for next day
-        taskRepository.resetFinishedForUser(userId);
+        taskRepository.resetStatusForUser(userId, TaskStatus.NOT_STARTED);
 
         DailyCompletionDto dto = new DailyCompletionDto(savedCompletion.getDailyCompletionId(),
