diff --git a/src/main/java/se/su/dsv/seshat/controllers/FileController.java b/src/main/java/se/su/dsv/seshat/controllers/FileController.java
index bd61b10..a7dd87a 100644
--- a/src/main/java/se/su/dsv/seshat/controllers/FileController.java
+++ b/src/main/java/se/su/dsv/seshat/controllers/FileController.java
@@ -1,5 +1,7 @@
 package se.su.dsv.seshat.controllers;
 
+import io.github.wimdeblauwe.htmx.spring.boot.mvc.HtmxResponse;
+import io.github.wimdeblauwe.htmx.spring.boot.mvc.HxRequest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.core.io.FileSystemResource;
@@ -15,19 +17,19 @@ import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.servlet.View;
+import org.springframework.web.servlet.view.FragmentsRendering;
 import se.su.dsv.seshat.entities.AppUser;
 import se.su.dsv.seshat.entities.FileMetadata;
+import se.su.dsv.seshat.entities.JobStatus;
 import se.su.dsv.seshat.services.JobProcessorService;
 import se.su.dsv.seshat.services.StorageService;
 import se.su.dsv.seshat.services.UserService;
 
 import java.io.File;
 import java.time.LocalDate;
-import java.util.Comparator;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.stream.Collectors;
 
 
 @Controller
@@ -44,42 +46,53 @@ public class FileController {
         this.jobProcessorService = jobProcessorService;
     }
 
+    @HxRequest
+    @GetMapping("/files/transcribed-files")
+    public String getTranscribedFiles(Authentication authentication, Model model) {
+        AppUser user = userService.getUserByUsername(authentication.getName());
+        Map<FileMetadata, List<FileMetadata>> filesByDirectory = storageService.getTranscribedFilesByDirectory(user);
+        model.addAttribute("filesByDirectory", filesByDirectory);
+        return "file-management :: transcribed-files";
+    }
+
+
+    @HxRequest
+    @GetMapping("/files/file-upload-statuses")
+    public View getFileUploadStatuses(Authentication authentication, Model model, HtmxResponse htmxResponse) {
+        AppUser user = userService.getUserByUsername(authentication.getName());
+        List<FileMetadata> uploaded = storageService.getUserUplaods(user);
+
+        List<FileMetadata> fileUploadStatuses = getFileUploadStatuses(uploaded);
+        boolean hasJobInProgress = hasJobInProgress(fileUploadStatuses);
+
+        model.addAttribute("fileUploadStatuses", fileUploadStatuses);
+        model.addAttribute("hasJobInProgress", hasJobInProgress);
+
+        if(hasJobInProgress) {
+            // return "file-management :: file-upload-statuses";
+            return FragmentsRendering.with("file-management :: file-upload-statuses").build();
+
+        }
+
+        htmxResponse.addTrigger("transcription-finished");
+        return FragmentsRendering.with("file-management :: file-upload-statuses-no-jobs").build();
+    }
+
     @GetMapping("/files/manage")
     public String showFileManagementPage(Authentication authentication, Model model) {
         AppUser user = userService.getUserByUsername(authentication.getName());
-        List<FileMetadata> files = storageService.getUserTranscriptons(user);
         List<FileMetadata> uploaded = storageService.getUserUplaods(user);
 
-        List<FileMetadata> statuses = uploaded.stream()
+        List<FileMetadata> fileUploadStatuses = uploaded.stream()
                 .filter(file -> file.getJobStatus() != null)
                 .toList();
 
-        // Map<String, List<FileMetadata>> filesByDirectory = files.stream().collect(Collectors.groupingBy(FileMetadata::getOutputDirectory));
-
-        Map<FileMetadata, List<FileMetadata>> filesByDirectory = files.stream()
-                .collect(Collectors.groupingBy(outputFile -> {
-                    return uploaded.stream()
-                            .filter(uploadedFile -> uploadedFile.getOutputDirectory().equals(outputFile.getOutputDirectory()))
-                            .filter(uploadedFile -> outputFile.getSourceFile().equals(uploadedFile.getFilePath()))
-                            .findFirst()
-                            .orElseThrow(/* Will never happen */);
-
-                }));
-
-        Map<FileMetadata, List<FileMetadata>> sortedFilesByDirectory = filesByDirectory.entrySet().stream()
-                .sorted(Map.Entry.comparingByKey(Comparator.comparing(FileMetadata::getUploadedAt).reversed()))
-                .collect(Collectors.toMap(
-                        Map.Entry::getKey,
-                        Map.Entry::getValue,
-                        (e1, e2) -> {
-                            e1.addAll(e2);
-                            return e1;
-                        },
-                        LinkedHashMap::new
-                ));
+        boolean hasJobInProgress = hasJobInProgress(fileUploadStatuses);
 
+        Map<FileMetadata, List<FileMetadata>> sortedFilesByDirectory = storageService.getTranscribedFilesByDirectory(user);
         model.addAttribute("filesByDirectory", sortedFilesByDirectory);
-        model.addAttribute("statuses", statuses);
+        model.addAttribute("fileUploadStatuses", fileUploadStatuses);
+        model.addAttribute("hasJobInProgress", hasJobInProgress);
 
         return "file-management";
     }
@@ -100,6 +113,7 @@ public class FileController {
             model.addAttribute("message", "File uploaded successfully. Transcription will start shortly.");
 
         } catch (Exception e) {
+            logger.error("Error uploading file", e);
             model.addAttribute("error", "File upload failed: " + e.getMessage());
         }
 
@@ -169,4 +183,16 @@ public class FileController {
         return "redirect:/files/manage";
     }
 
+    private static List<FileMetadata> getFileUploadStatuses(List<FileMetadata> uploaded) {
+        return uploaded.stream()
+                .filter(file -> file.getJobStatus() != null)
+                .toList();
+    }
+
+    private static boolean hasJobInProgress(List<FileMetadata> fileUploadStatuses) {
+        return fileUploadStatuses.stream()
+                .anyMatch(file -> file.getJobStatus().equals(JobStatus.PROCESSING) ||
+                        file.getJobStatus().equals(JobStatus.PENDING));
+    }
+
 }
diff --git a/src/main/java/se/su/dsv/seshat/services/StorageService.java b/src/main/java/se/su/dsv/seshat/services/StorageService.java
index 4971a38..7f67d7f 100644
--- a/src/main/java/se/su/dsv/seshat/services/StorageService.java
+++ b/src/main/java/se/su/dsv/seshat/services/StorageService.java
@@ -22,7 +22,10 @@ import java.nio.file.StandardCopyOption;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 import java.util.stream.Collectors;
 import java.util.zip.ZipEntry;
@@ -176,7 +179,7 @@ public class StorageService {
                 } catch (IllegalArgumentException e) {
                     return false;
                 } catch (IOException e) {
-                    logger.info("Failed to delete file or directory: " + e.getMessage());
+                    logger.info("Failed to delete file or directory: {}", e.getMessage());
                 }
             } else {
                 return false;
@@ -227,15 +230,38 @@ public class StorageService {
         return zipFile;
     }
 
+    public Map<FileMetadata, List<FileMetadata>> getTranscribedFilesByDirectory(AppUser user) {
+        List<FileMetadata> files = this.getUserTranscriptons(user);
+        List<FileMetadata> uploaded = this.getUserUplaods(user);
+
+        Map<FileMetadata, List<FileMetadata>> filesByDirectory = files.stream()
+                .collect(Collectors.groupingBy(outputFile -> uploaded.stream()
+                        .filter(uploadedFile -> uploadedFile.getOutputDirectory().equals(outputFile.getOutputDirectory()))
+                        .filter(uploadedFile -> outputFile.getSourceFile().equals(uploadedFile.getFilePath()))
+                        .findFirst()
+                        .orElseThrow(/* Will never happen */)));
+
+        return filesByDirectory.entrySet().stream()
+                .sorted(Map.Entry.comparingByKey(Comparator.comparing(FileMetadata::getUploadedAt).reversed()))
+                .collect(Collectors.toMap(
+                        Map.Entry::getKey,
+                        Map.Entry::getValue,
+                        (e1, e2) -> {
+                            e1.addAll(e2);
+                            return e1;
+                        },
+                        LinkedHashMap::new
+                ));
+    }
+
     private String sanitizeFilename(String filename) {
         return filename.replaceAll("[^a-zA-Z0-9.-]", "_");
     }
 
     private String fileNameAndUploadedTime(FileMetadata file) {
-        String fileName = file.getFileName();
         LocalDateTime uploadedAt = file.getUploadedAt();
         String uploadedToSeconds = uploadedAt.truncatedTo(ChronoUnit.SECONDS).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
-        return fileNameWithoutExtension(file.getFileName()) + "_" + uploadedToSeconds.replaceAll(":|-", "");
+        return fileNameWithoutExtension(file.getFileName()) + "_" + uploadedToSeconds.replaceAll("[:\\-]", "");
     }
 
     private String fileNameWithoutExtension(String fileName) {
diff --git a/src/main/java/se/su/dsv/seshat/services/Transcriber.java b/src/main/java/se/su/dsv/seshat/services/Transcriber.java
index 3d1fc5f..e8011a2 100644
--- a/src/main/java/se/su/dsv/seshat/services/Transcriber.java
+++ b/src/main/java/se/su/dsv/seshat/services/Transcriber.java
@@ -11,11 +11,11 @@ import java.io.IOException;
 public class Transcriber {
 
     private static final Logger logger = LoggerFactory.getLogger(Transcriber.class);
-    private String modelPath;
-    private String selectedModel;
-    private String workingDirectory;
+    private final String modelPath;
+    private final String selectedModel;
+    private final String workingDirectory;
     ProcessBuilder startVirtualEnv;
-    private String selectedDevice;
+    private final String selectedDevice;
 
     public Transcriber(WhisperProperties whisperProperties) {
         modelPath = whisperProperties.modelPath();
@@ -32,7 +32,7 @@ public class Transcriber {
             Process p = startVirtualEnv.start();
             p.waitFor();
         } catch (Exception e) {
-            logger.error("Failed to activate virtual environment: " + e.getMessage());
+            logger.error("Failed to activate virtual environment: {}", e.getMessage());
         }
     }
 
diff --git a/src/main/resources/templates/file-management.html b/src/main/resources/templates/file-management.html
index 5b75a20..dda4084 100644
--- a/src/main/resources/templates/file-management.html
+++ b/src/main/resources/templates/file-management.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<html xmlns:th="http://www.thymeleaf.org" xmlns:hx-get="http://www.w3.org/1999/xhtml" lang="en">
+<html xmlns:th="http://www.thymeleaf.org" lang="en">
 <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -28,7 +28,6 @@
 
 <main class="container mt-4">
     <h2>File Management</h2>
-
     <!-- File Upload Section -->
     <section>
         <h3>Upload File</h3>
@@ -53,10 +52,9 @@
             <button type="submit" class="btn btn-primary">Upload</button>
         </form>
     </section>
-
     <!-- File Status Section -->
-    <section th:if="${statuses != null && !statuses.isEmpty()}" class="mt-5">
-        <h3>File Upload Statuses</h3>
+    <section th:if="${fileUploadStatuses != null && !fileUploadStatuses.isEmpty()}" class="mt-5">
+        <h3>File Upload History</h3>
         <div class="table-wrapper">
             <table class="table">
                 <thead>
@@ -67,15 +65,34 @@
                     <th>Status</th>
                 </tr>
                 </thead>
-                <tbody>
-                <tr th:each="status : ${statuses}">
-                    <td th:text="${status.fileName}">File Name</td>
-                    <td th:text="${#temporals.format(status.getUploadedAt(), 'yyyy-MM-dd')}">Upload Date</td>
-                    <td th:text="${#temporals.format(status.getUploadedAt(), 'HH:mm:ss')}">Upload time</td>
-                    <td>
-                        <span class="badge bg-primary" th:text="${status.jobStatus}">Status</span>
-                    </td>
-                </tr>
+                    <tbody th:if="${hasJobInProgress == true}"
+                           th:fragment="file-upload-statuses"
+                           hx-get="/files/file-upload-statuses"
+                           hx-trigger="load delay:10s"
+                           hx-swap="outerHTML">
+                        <tr th:each="uploadStatus : ${fileUploadStatuses}">
+                            <td th:text="${uploadStatus.fileName}">File Name</td>
+                            <td th:text="${#temporals.format(uploadStatus.getUploadedAt(), 'yyyy-MM-dd')}">Upload Date</td>
+                            <td th:text="${#temporals.format(uploadStatus.getUploadedAt(), 'HH:mm:ss')}">Upload time</td>
+                            <td>
+                                <span class="badge bg-primary" th:text="${uploadStatus.jobStatus}">Status</span>
+                                <span th:if="${uploadStatus.jobStatus == uploadStatus.jobStatus.PENDING ||
+                                               uploadStatus.jobStatus == uploadStatus.jobStatus.PROCESSING}">
+                                    <span class="spinner-border spinner-border-sm text-primary" role="status"></span>
+                                </span>
+                            </td>
+                        </tr>
+                    </tbody>
+                <tbody th:unless="${hasJobInProgress == true}"
+                       th:fragment="file-upload-statuses-no-jobs">
+                    <tr th:each="uploadStatus : ${fileUploadStatuses}">
+                        <td th:text="${uploadStatus.fileName}">File Name</td>
+                        <td th:text="${#temporals.format(uploadStatus.getUploadedAt(), 'yyyy-MM-dd')}">Upload Date</td>
+                        <td th:text="${#temporals.format(uploadStatus.getUploadedAt(), 'HH:mm:ss')}">Upload time</td>
+                        <td>
+                            <span class="badge bg-primary" th:text="${uploadStatus.jobStatus}">Status</span>
+                        </td>
+                    </tr>
                 </tbody>
             </table>
         </div>
@@ -86,7 +103,13 @@
     <!-- File Browsing Section -->
     <section>
         <h3>Your Transcribed Files</h3>
-        <form id="bulk-actions-form" method="post">
+        <form th:fragment="transcribed-files"
+              id="bulk-actions-form"
+              hx-trigger="transcription-finished from:body"
+              hx-get="/files/transcribed-files"
+              hx-swap="outerHTML"
+              method="post"
+              class="transcribed-files">
             <div th:each="entry : ${filesByDirectory}">
 
                 <a data-bs-toggle="collapse"
@@ -132,8 +155,8 @@
 <footer class="bg-primary text-white text-center py-3">
     <p>&copy; 2024 Seshat App</p>
 </footer>
-<script type="text/javascript" th:src="@{/js/script.js}"></script>
 <script type="text/javascript" th:src="@{/3p/bootstrap-5.3.3-dist/js/bootstrap.bundle.min.js}"></script>
 <script type="text/javascript" th:src="@{/3p/htmx/2.0.4/dist/htmx.min.js}"></script>
+<script type="text/javascript" th:src="@{/js/script.js}"></script>
 </body>
 </html>