diff --git a/src/invidious/routes/search.cr b/src/invidious/routes/search.cr
index 6c3088de..edf0351c 100644
--- a/src/invidious/routes/search.cr
+++ b/src/invidious/routes/search.cr
@@ -59,17 +59,21 @@ module Invidious::Routes::Search
         return error_template(500, ex)
       end
 
-      params = query.to_http_params
-      url_prev_page = "/search?#{params}&page=#{query.page - 1}"
-      url_next_page = "/search?#{params}&page=#{query.page + 1}"
-
       redirect_url = Invidious::Frontend::Misc.redirect_url(env)
 
+      # Pagination
+      page_nav_html = Frontend::Pagination.nav_numeric(locale,
+        base_url: "/search?#{query.to_http_params}",
+        current_page: query.page,
+        show_next: (videos.size >= 20)
+      )
+
       if query.type == Invidious::Search::Query::Type::Channel
         env.set "search", "channel:#{query.channel} #{query.text}"
       else
         env.set "search", query.text
       end
+
       templated "search"
     end
   end
@@ -96,11 +100,13 @@ module Invidious::Routes::Search
       return error_template(500, ex)
     end
 
-    params = env.params.query.empty? ? "" : "&#{env.params.query}"
-
+    # Pagination
     hashtag_encoded = URI.encode_www_form(hashtag, space_to_plus: false)
-    url_prev_page = "/hashtag/#{hashtag_encoded}?page=#{page - 1}#{params}"
-    url_next_page = "/hashtag/#{hashtag_encoded}?page=#{page + 1}#{params}"
+    page_nav_html = Frontend::Pagination.nav_numeric(locale,
+      base_url: "/hashtag/#{hashtag_encoded}",
+      current_page: page,
+      show_next: (videos.size >= 60)
+    )
 
     templated "hashtag"
   end
diff --git a/src/invidious/views/hashtag.ecr b/src/invidious/views/hashtag.ecr
index 3351c21c..2000337e 100644
--- a/src/invidious/views/hashtag.ecr
+++ b/src/invidious/views/hashtag.ecr
@@ -4,38 +4,5 @@
 
 <hr/>
 
-<div class="pure-g h-box v-box">
-    <div class="pure-u-1 pure-u-lg-1-5">
-        <%- if page > 1 -%>
-            <a href="<%= url_prev_page %>"><%= translate(locale, "Previous page") %></a>
-        <%- end -%>
-    </div>
-    <div class="pure-u-1 pure-u-lg-3-5"></div>
-    <div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
-        <%- if videos.size >= 60 -%>
-            <a href="<%= url_next_page %>"><%= translate(locale, "Next page") %></a>
-        <%- end -%>
-    </div>
-</div>
 
-<div class="pure-g">
-    <%- videos.each do |item| -%>
-        <%= rendered "components/item" %>
-    <%- end -%>
-</div>
-
-<script src="/js/watched_indicator.js"></script>
-
-<div class="pure-g h-box">
-    <div class="pure-u-1 pure-u-lg-1-5">
-        <%- if page > 1 -%>
-            <a href="<%= url_prev_page %>"><%= translate(locale, "Previous page") %></a>
-        <%- end -%>
-    </div>
-    <div class="pure-u-1 pure-u-lg-3-5"></div>
-    <div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
-        <%- if videos.size >= 60 -%>
-            <a href="<%= url_next_page %>"><%= translate(locale, "Next page") %></a>
-        <%- end -%>
-    </div>
-</div>
+<%= rendered "components/items_paginated" %>
diff --git a/src/invidious/views/search.ecr b/src/invidious/views/search.ecr
index a7469e36..627a13b0 100644
--- a/src/invidious/views/search.ecr
+++ b/src/invidious/views/search.ecr
@@ -7,19 +7,6 @@
 <%= Invidious::Frontend::SearchFilters.generate(query.filters, query.text, query.page, locale) %>
 <hr/>
 
-<div class="pure-g h-box v-box">
-    <div class="pure-u-1 pure-u-lg-1-5">
-        <%- if query.page > 1 -%>
-            <a href="<%= url_prev_page %>"><%= translate(locale, "Previous page") %></a>
-        <%- end -%>
-    </div>
-    <div class="pure-u-1 pure-u-lg-3-5"></div>
-    <div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
-        <%- if videos.size >= 20 -%>
-            <a href="<%= url_next_page %>"><%= translate(locale, "Next page") %></a>
-        <%- end -%>
-    </div>
-</div>
 
 <%- if videos.empty? -%>
 <div class="h-box no-results-error">
@@ -30,25 +17,5 @@
     </div>
 </div>
 <%- else -%>
-<div class="pure-g">
-    <%- videos.each do |item| -%>
-        <%= rendered "components/item" %>
-    <%- end -%>
-</div>
+    <%= rendered "components/items_paginated" %>
 <%- end -%>
-
-<script src="/js/watched_indicator.js"></script>
-
-<div class="pure-g h-box">
-    <div class="pure-u-1 pure-u-lg-1-5">
-        <%- if query.page > 1 -%>
-            <a href="<%= url_prev_page %>"><%= translate(locale, "Previous page") %></a>
-        <%- end -%>
-    </div>
-    <div class="pure-u-1 pure-u-lg-3-5"></div>
-    <div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
-        <%- if videos.size >= 20 -%>
-            <a href="<%= url_next_page %>"><%= translate(locale, "Next page") %></a>
-        <%- end -%>
-    </div>
-</div>