Volltextsuche für eine statische Website

Neulich wollten wir auf unserer eigenen Seite nachschauen, wo wir schon über PPS und PPSU geschrieben haben – und haben gemerkt: Es gibt keine Suche. Bei inzwischen rund 160 Seiten Knowledgebase, Projekten und Blog ist das ein echtes Manko. Seit heute gibt es oben rechts in der Navigation ein Suchfeld. Hier steht, wie wir das gelöst haben.

Das Problem: keine Datenbank, kein Server

Unsere Website ist statisch. Ein selbst geschriebener Generator (ssg2) baut aus Markdown-Dateien fertige HTML-Seiten, die dann einfach auf den Webserver kopiert werden. Es gibt keine Datenbank und kein Programm, das auf dem Server läuft. Genau das macht die Seite schnell, sicher und billig – aber eine Suche, wie man sie von Wordpress & Co. kennt, fällt damit weg. Die fragt bei jeder Eingabe die Datenbank.

Die Möglichkeiten

Ansatz Vorteil Warum nicht
Google-Suchfeld einbetten in fünf Minuten erledigt lädt Google-Skripte und Werbung, übermittelt Suchanfragen an Google – passt nicht zu unserer Datenschutzerklärung („keine externen Ressourcen“)
Suchdienst als Cloud-Service (Algolia u. ä.) sehr komfortabel externer Dienst, Konto, Kosten, wieder Daten bei Dritten
Eigenes Suchprogramm auf dem Server volle Kontrolle widerspricht dem ganzen Konzept einer statischen Seite
Suchindex im Browser (lunr.js, Fuse.js) läuft ohne Server der komplette Index muss bei jeder Suche geladen werden – bei 160 Seiten mehrere Megabyte
Pagefind läuft ohne Server, lädt nur die nötigen Teile des Index ✅ unsere Wahl

Was Pagefind anders macht

Pagefind läuft einmal nach dem Bau der Website über alle HTML-Seiten und schreibt einen Suchindex als lauter kleine Dateien in einen Ordner pagefind/. Dieser Ordner wird mit der Website hochgeladen, mehr braucht es auf dem Server nicht.

Im Browser passiert dann Folgendes:

  1. Beim ersten Tastendruck lädt Pagefind ein kleines Programm (als WebAssembly) und eine Übersicht des Index.
  2. Für jedes Suchwort holt es nur den Teil des Index, in dem dieses Wort steht – nicht den ganzen.
  3. Für die Treffer lädt es kurze Textausschnitte und zeigt sie mit hervorgehobenem Suchwort an.

Bei unseren 156 indexierten Seiten ist der gesamte Index rund 2 MB groß. Eine typische Suche lädt davon aber nur einen kleinen Bruchteil. Und weil die Seiten auf Deutsch sind (<html lang="de">), nutzt Pagefind deutsche Wortstämme: Wer „Kondensatoren“ sucht, findet auch „Kondensator“.

Datenschutz: Alles liegt auf unserem eigenen Server. Es wird nichts an Dritte geschickt, es gibt keine Cookies und kein Tracking der Suchanfragen.

So haben wir es eingebaut

1. Pagefind installieren

Pagefind gibt es als Python-Paket, das das eigentliche Programm gleich mitbringt. Das passt gut, weil unser Generator ohnehin in Python geschrieben ist:

pip install "pagefind[extended]"

2. Nur echte Inhalte indexieren

Eine Suche, die Entwürfe, halbfertige Seiten oder bei jedem Treffer die Navigation mitliefert, nützt niemandem. Pagefind kennt dafür ein Attribut: Sobald irgendeine Seite einen Bereich mit data-pagefind-body markiert, indexiert es nur noch markierte Seiten und davon nur diesen Bereich.

Unser Generator weiß ohnehin, welche Seiten veröffentlicht sind – er braucht diese Liste schon für die Sitemap und den RSS-Feed. Nach dem Bauen setzt er deshalb auf genau diesen Seiten das Attribut an den Hauptinhalt:

def mark_search_body(pages):
    """Setzt data-pagefind-body auf das erste <main> jeder Seite."""
    for page in pages:
        text = page.read_text(encoding="utf-8")
        if "data-pagefind-body" in text:
            continue
        text = re.sub(r"<main(\s|>)", r"<main data-pagefind-body\1", text, count=1)
        page.write_text(text, encoding="utf-8")

Entwürfe, Platzhalter-Seiten („in Arbeit“) und Seiten mit noindex bekommen das Attribut nicht und landen damit auch nicht im Suchindex. Navigation und Fußzeile liegen außerhalb von <main> und bleiben automatisch draußen. Die Seitenleiste „Neueste Beiträge“ steht zwar in <main>, ist aber mit data-pagefind-ignore ausgenommen – sonst wäre jeder Artikel ein Treffer für die Titel der neuesten Beiträge.

3. Pagefind nach dem Bauen aufrufen

Danach ruft der Generator Pagefind auf:

subprocess.run([sys.executable, "-m", "pagefind", "--site", str(output_dir)])

Eingeschaltet wird das pro Website mit einer Zeile in der Konfiguration (search: pagefind). Unsere zweite Seite, kleinemoba.de, baut also unverändert ohne Suche, bis wir es dort auch wollen.

4. Suchseite und Suchfeld

Pagefind bringt eine fertige Oberfläche mit. Die Suchseite besteht im Kern aus wenigen Zeilen:

<link href="/pagefind/pagefind-ui.css" rel="stylesheet">
<div id="suche"></div>
<script src="/pagefind/pagefind-ui.js"></script>
<script>
  const ui = new PagefindUI({ element: "#suche", showSubResults: true });
  const q = new URLSearchParams(location.search).get("q");
  if (q) ui.triggerSearch(q);
</script>

Das Suchfeld in der Navigationsleiste ist ein ganz normales Formular, das auf diese Seite verweist (/suche.html?q=…). Die letzten beiden Zeilen im Skript übernehmen den Suchbegriff aus der Adresse und starten die Suche sofort.

Was es kostet

Ausprobieren

Oben rechts im Suchfeld zum Beispiel PPS, Hall-Sensor oder NE555 eingeben. Und falls etwas nicht gefunden wird, das eigentlich da sein müsste: Schreibt uns, dann sehen wir uns das an.


Erstellt: 07.10.2026 · Zuletzt geändert: 06.10.2026