← blog

Building static full-text search without Lunr or Pagefind

2026-01-18 · Finn O'Brien

Adding full-text search to a static site generator without pulling in a JavaScript framework is a fun constraint. Here's the approach StoneBark 1.0 uses.

Build-time index

At build time, StoneBark reads every page, strips HTML tags, tokenises the text, and builds an inverted index: a map from term to the list of (document, position) pairs where it appears. This is written as a single JSON file, search-index.json, alongside the rest of the site output.

The index includes stemmed terms (using a simple Porter stemmer for English) alongside the raw terms, so searching for "rendering" also finds "rendered" and "renders".

The frontend

The search frontend is about 80 lines of vanilla JavaScript embedded directly in the default theme's base.html. It fetches the index file on first keypress (not on page load), caches it in a module variable, and queries it synchronously. No web workers, no IndexedDB.

Performance is acceptable for sites up to about 500 pages. Beyond that the index gets large enough to warrant a more sophisticated approach, which is outside StoneBark's intended scope.

Why not Pagefind

Pagefind is excellent and I'd recommend it for large sites. For small sites it requires a post-processing step that complicates the build pipeline, and it brings in a WASM binary dependency. StoneBark's search is intentionally less capable but requires nothing beyond what stonebark build already produces.


Also: StoneBark 1.0: stable API and full-text search