Index: src/main/java/it/finki/charitable/controller/DonationPostController.java
===================================================================
--- src/main/java/it/finki/charitable/controller/DonationPostController.java	(revision 0f4f5521e24d4ce3122add41ffb78a46c75e0500)
+++ src/main/java/it/finki/charitable/controller/DonationPostController.java	(revision 276a8b675a5b68c01f48d3efcbfe41e2f836ed6c)
@@ -4,4 +4,5 @@
 import it.finki.charitable.services.*;
 import it.finki.charitable.util.FileUploadUtil;
+import org.springframework.data.domain.Page;
 import org.springframework.format.annotation.DateTimeFormat;
 import org.springframework.security.core.context.SecurityContextHolder;
@@ -122,10 +123,14 @@
 
     @RequestMapping("/album")
-    public String album(Model model) {
-        List<DonationPost> postList = donationPostService.findAllByApproved(true);
-        if (postList.size() == 0) {
+    public String album(Model model,
+                        @RequestParam int page,
+                        @RequestParam String sort,
+                        @RequestParam(required = false,defaultValue = "") String order) {
+        Page<DonationPost> postList = donationPostService.findPaginated(page,6, sort, order);
+        if (postList.getSize() == 0) {
             model.addAttribute("noPosts", true);
             return "album";
         }
+        model.addAttribute("totalPages", postList.getTotalPages());
         model.addAttribute("postList", postList);
         return "album";
Index: src/main/java/it/finki/charitable/repository/DonationPostRepository.java
===================================================================
--- src/main/java/it/finki/charitable/repository/DonationPostRepository.java	(revision 0f4f5521e24d4ce3122add41ffb78a46c75e0500)
+++ src/main/java/it/finki/charitable/repository/DonationPostRepository.java	(revision 276a8b675a5b68c01f48d3efcbfe41e2f836ed6c)
@@ -4,4 +4,6 @@
 import it.finki.charitable.entities.DonationPost;
 import it.finki.charitable.entities.Moderator;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.stereotype.Repository;
@@ -14,3 +16,4 @@
     List<DonationPost> findAllByApproved(Boolean approved);
     List<DonationPost> findAllByModerator(Moderator moderator);
+    Page<DonationPost> findAllByApproved(Pageable pageable, boolean approved);
 }
Index: src/main/java/it/finki/charitable/services/DonationPostService.java
===================================================================
--- src/main/java/it/finki/charitable/services/DonationPostService.java	(revision 0f4f5521e24d4ce3122add41ffb78a46c75e0500)
+++ src/main/java/it/finki/charitable/services/DonationPostService.java	(revision 276a8b675a5b68c01f48d3efcbfe41e2f836ed6c)
@@ -54,7 +54,9 @@
     }
 
-    public Page<DonationPost> findPaginated(int pageNo, int pageSize, String sort) {
-        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by(sort));
-        return donationPostRepository.findAll(pageable);
+    public Page<DonationPost> findPaginated(int pageNo, int pageSize, String sort, String order) {
+        Sort s = Sort.by(sort);
+        s = order.equals("asc") ? s.ascending() : s.descending();
+        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, s);
+        return donationPostRepository.findAllByApproved(pageable, true);
     }
 }
Index: src/main/resources/static/js/pagination.js
===================================================================
--- src/main/resources/static/js/pagination.js	(revision 276a8b675a5b68c01f48d3efcbfe41e2f836ed6c)
+++ src/main/resources/static/js/pagination.js	(revision 276a8b675a5b68c01f48d3efcbfe41e2f836ed6c)
@@ -0,0 +1,99 @@
+let url = window.location.href.toString().split(window.location.host)[1].split("?")[0];
+
+let pages = parseInt(document.getElementById("helper").getAttribute("data-pages"));
+let currentPage = parseInt(findGetParameter("page"));
+let sort = findGetParameter("sort");
+let order = findGetParameter("order");
+
+let sortByInput = document.getElementById("sortBy");
+sortByInput.value = sort;
+
+let orderInput = document.getElementById("order");
+orderInput.value = order;
+
+sortByInput.addEventListener("change", function () {
+    window.location.href = url + "?page=" + currentPage + "&sort=" + sortByInput.value + "&order=" + orderInput.value;
+})
+
+orderInput.addEventListener("change", function() {
+    window.location.href = url + "?page=" + currentPage + "&sort=" + sortByInput.value + "&order=" + orderInput.value;
+})
+
+document.getElementById('pagination').innerHTML = createPagination(pages, currentPage);
+
+function createPagination(pages, page) {
+    let str = '<ul class="pagination justify-content-center">';
+    let active;
+    let pagesBefore = page - 1;
+    let pagesAfter = page + 1;
+
+    if (page > 1) {
+        str += '<li class="page-item"><a class="page-link" href="'+url+'?page='+(page-1)+'&sort='+sort+'&order='+order+'">Previous</a></li>';
+    }
+
+    if (pages < 6) {
+        for (let p = 1; p <= pages; p++) {
+            active = page == p ? "active" : "";
+            str += '<li class="page-item '+active+'"><a class="page-link" href="'+url+'?page='+p+'&sort='+sort+'&order='+order+'">'+ p +'</a></li>';
+        }
+    }
+
+    else {
+        if (page > 2) {
+            str += '<li class="page-item"><a class="page-link" href="'+url+'?page=1&sort='+sort+'&order='+order+'">1</a></li>';
+            if (page > 3) {
+                str += '<li class="page-item"><a class="page-link" href="'+url+'?page='+(page-2)+'&sort='+sort+'&order='+order+'">...</a></li>';
+            }
+        }
+
+        if (page === 1) {
+            pagesAfter += 2;
+        } else if (page === 2) {
+            pagesAfter += 1;
+        }
+
+        if (page === pages) {
+            pagesBefore -= 2;
+        } else if (page === pages-1) {
+            pagesBefore -= 1;
+        }
+
+        for (let p = pagesBefore; p <= pagesAfter; p++) {
+            if (p === 0) {
+                p += 1;
+            }
+            if (p > pages) {
+                continue
+            }
+            active = page == p ? "active" : "";
+            str += '<li class="page-item '+active+'"><a class="page-link" href="'+url+'?page='+p+'&sort='+sort+'&order='+order+'">'+ p +'</a></li>';
+        }
+
+        if (page < pages-1) {
+            if (page < pages-2) {
+                str += '<li class="page-item"><a class="page-link" href="'+url+'?page='+(page+2)+'&sort='+sort+'&order='+order+'">...</a></li>';
+            }
+            str += '<li class="page-item"><a class="page-link" href="'+url+'?page='+pages+'&sort='+sort+'&order='+order+'">'+pages+'</a></li>';
+        }
+    }
+
+    if (page < pages) {
+        str += '<li class="page-item"><a class="page-link" href="'+url+'?page='+(page+1)+'&sort='+sort+'&order='+order+'">Next</a></li>';
+    }
+    str += '</ul>';
+
+    return str;
+}
+
+function findGetParameter(parameterName) {
+    let result = null,
+        tmp = [];
+    location.search
+        .substr(1)
+        .split("&")
+        .forEach(function (item) {
+            tmp = item.split("=");
+            if (tmp[0] === parameterName) result = tmp[1];
+        });
+    return result;
+}
Index: src/main/resources/templates/album.html
===================================================================
--- src/main/resources/templates/album.html	(revision 0f4f5521e24d4ce3122add41ffb78a46c75e0500)
+++ src/main/resources/templates/album.html	(revision 276a8b675a5b68c01f48d3efcbfe41e2f836ed6c)
@@ -16,6 +16,25 @@
     <p th:if="${noPosts}">No posts</p>
     <div th:unless="${noPosts}" class="album py-5 bg-light">
+
         <div class="container">
-
+            <div class="row">
+                <div class="col-md-2">
+                    <label class="form-label" for="sortBy">Sort By</label>
+                    <select class="input-group-text" id="sortBy">
+                        <option value="id">Default</option>
+                        <option value="title">Title</option>
+                        <option value="dateDue">Date due</option>
+                        <option value="fundsNeeded">Funds needed</option>
+                    </select>
+                </div>
+                <div class="col-md-2">
+                    <label class="form-label" for="order">Order</label>
+                    <select class="input-group-text" id="order">
+                        <option value="asc">Ascending</option>
+                        <option value="desc">Descending</option>
+                    </select>
+                </div>
+            </div>
+            <br>
             <div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3">
                 <div class="col" th:each="post : ${postList}">
@@ -37,13 +56,7 @@
             </div>
         </div>
-        <hr class="ui-menu-divider" />
+        <hr class="ui-menu-divider"/>
         <nav>
-            <ul class="pagination justify-content-center">
-                <li class="page-item"><a class="page-link" href="#">Previous</a></li>
-                <li class="page-item"><a class="page-link" href="#">1</a></li>
-                <li class="page-item"><a class="page-link" href="#">2</a></li>
-                <li class="page-item"><a class="page-link" href="#">3</a></li>
-                <li class="page-item"><a class="page-link" href="#">Next</a></li>
-            </ul>
+            <div id="pagination"></div>
         </nav>
     </div>
@@ -51,4 +64,5 @@
 </main>
 <script src="/js/bootstrap.min.js"></script>
+<script id="helper" src="/js/pagination.js" th:data-pages="${totalPages}"></script>
 </body>
 </html>
Index: src/main/resources/templates/common/navbar.html
===================================================================
--- src/main/resources/templates/common/navbar.html	(revision 0f4f5521e24d4ce3122add41ffb78a46c75e0500)
+++ src/main/resources/templates/common/navbar.html	(revision 276a8b675a5b68c01f48d3efcbfe41e2f836ed6c)
@@ -23,5 +23,5 @@
                     </li>
                     <li class="nav-item">
-                        <a sec:authorize="isAnonymous() or hasAuthority('USER')" th:href="@{/album?page=1}" class="nav-link px-2 text-white">Posts</a>
+                        <a sec:authorize="isAnonymous() or hasAuthority('USER')" th:href="@{/album?page=1&sort=id}" class="nav-link px-2 text-white">Posts</a>
                         <a sec:authorize="hasAuthority('MODERATOR')" th:href="@{/moderator/approval}" class="nav-link px-2 text-white">Posts for approval</a>
                     </li>
