diff --git a/src/pages/search.jsx b/src/pages/search.jsx
index 5b451e3b..24b52faa 100644
--- a/src/pages/search.jsx
+++ b/src/pages/search.jsx
@@ -1,7 +1,14 @@
 import './search.css';
 
 import { forwardRef } from 'preact/compat';
-import { useEffect, useImperativeHandle, useRef, useState } from 'preact/hooks';
+import {
+  useEffect,
+  useImperativeHandle,
+  useLayoutEffect,
+  useRef,
+  useState,
+} from 'preact/hooks';
+import { InView } from 'react-intersection-observer';
 import { useParams, useSearchParams } from 'react-router-dom';
 
 import AccountBlock from '../components/account-block';
@@ -13,6 +20,9 @@ import Status from '../components/status';
 import { api } from '../utils/api';
 import useTitle from '../utils/useTitle';
 
+const SHORT_LIMIT = 5;
+const LIMIT = 40;
+
 function Search(props) {
   const params = useParams();
   const { masto, instance, authenticated } = api({
@@ -40,35 +50,78 @@ function Search(props) {
     `/search`,
   );
 
+  const [showMore, setShowMore] = useState(false);
+  const offsetRef = useRef(0);
+  useEffect(() => {
+    offsetRef.current = 0;
+  }, [type]);
+
+  const scrollableRef = useRef();
+  useLayoutEffect(() => {
+    scrollableRef.current?.scrollTo?.(0, 0);
+  }, [q, type]);
+
   const [statusResults, setStatusResults] = useState([]);
   const [accountResults, setAccountResults] = useState([]);
   const [hashtagResults, setHashtagResults] = useState([]);
+
+  function loadResults(firstLoad) {
+    setUiState('loading');
+    if (firstLoad && !type) {
+      setStatusResults(statusResults.slice(0, SHORT_LIMIT));
+      setAccountResults(accountResults.slice(0, SHORT_LIMIT));
+      setHashtagResults(hashtagResults.slice(0, SHORT_LIMIT));
+    }
+
+    (async () => {
+      const params = {
+        q,
+        resolve: authenticated,
+        limit: SHORT_LIMIT,
+      };
+      if (type) {
+        params.limit = LIMIT;
+        params.type = type;
+        params.offset = offsetRef.current;
+      }
+      try {
+        const results = await masto.v2.search(params);
+        console.log(results);
+        if (type) {
+          if (type === 'statuses') {
+            setStatusResults((prev) => [...prev, ...results.statuses]);
+          } else if (type === 'accounts') {
+            setAccountResults((prev) => [...prev, ...results.accounts]);
+          } else if (type === 'hashtags') {
+            setHashtagResults((prev) => [...prev, ...results.hashtags]);
+          }
+          offsetRef.current = offsetRef.current + LIMIT;
+          setShowMore(!!results[type]?.length);
+        } else {
+          setStatusResults(results.statuses);
+          setAccountResults(results.accounts);
+          setHashtagResults(results.hashtags);
+        }
+        setUiState('default');
+      } catch (err) {
+        console.error(err);
+        setUiState('error');
+      }
+    })();
+  }
+
   useEffect(() => {
     // searchFieldRef.current?.focus?.();
     // searchFormRef.current?.focus?.();
     if (q) {
       // searchFieldRef.current.value = q;
       searchFormRef.current?.setValue?.(q);
-
-      setUiState('loading');
-      (async () => {
-        const results = await masto.v2.search({
-          q,
-          limit: type ? 40 : 5,
-          resolve: authenticated,
-          type,
-        });
-        console.log(results);
-        setStatusResults(results.statuses);
-        setAccountResults(results.accounts);
-        setHashtagResults(results.hashtags);
-        setUiState('default');
-      })();
+      loadResults(true);
     }
   }, [q, type, instance]);
 
   return (
-    <div id="search-page" class="deck-container">
+    <div id="search-page" class="deck-container" ref={scrollableRef}>
       <div class="timeline-deck deck">
         <header>
           <div class="header-grid">
@@ -110,7 +163,7 @@ function Search(props) {
                 ))}
             </div>
           )}
-          {!!q && uiState !== 'loading' ? (
+          {!!q ? (
             <>
               {(!type || type === 'accounts') && (
                 <>
@@ -140,6 +193,10 @@ function Search(props) {
                         </div>
                       )}
                     </>
+                  ) : uiState === 'loading' ? (
+                    <p class="ui-state">
+                      <Loader abrupt />
+                    </p>
                   ) : (
                     <p class="ui-state">No accounts found.</p>
                   )}
@@ -179,6 +236,10 @@ function Search(props) {
                         </div>
                       )}
                     </>
+                  ) : uiState === 'loading' ? (
+                    <p class="ui-state">
+                      <Loader abrupt />
+                    </p>
                   ) : (
                     <p class="ui-state">No hashtags found.</p>
                   )}
@@ -218,11 +279,48 @@ function Search(props) {
                         </div>
                       )}
                     </>
+                  ) : uiState === 'loading' ? (
+                    <p class="ui-state">
+                      <Loader abrupt />
+                    </p>
                   ) : (
                     <p class="ui-state">No posts found.</p>
                   )}
                 </>
               )}
+              {!!type &&
+                (uiState === 'default' ? (
+                  showMore ? (
+                    <InView
+                      onChange={(inView) => {
+                        if (inView) {
+                          loadResults();
+                        }
+                      }}
+                    >
+                      <button
+                        type="button"
+                        class="plain block"
+                        onClick={() => loadResults()}
+                        style={{ marginBlockEnd: '6em' }}
+                      >
+                        Show more&hellip;
+                      </button>
+                    </InView>
+                  ) : (
+                    <p class="ui-state insignificant">The end.</p>
+                  )
+                ) : (
+                  !!(
+                    hashtagResults.length ||
+                    accountResults.length ||
+                    statusResults.length
+                  ) && (
+                    <p class="ui-state">
+                      <Loader abrupt />
+                    </p>
+                  )
+                ))}
             </>
           ) : uiState === 'loading' ? (
             <p class="ui-state">