Adding search to a static site seems like a paradox. No server, no database, no backend — how do you query anything? The answer is that you do not need a runtime database. You build the index at deploy time and query it in the browser. Here are three approaches ranked by complexity.
Approach 1: The Pre-Built JSON Index
The simplest option works for most personal blogs and documentation sites. At build time, you generate a JSON file containing every post's title, slug, description, and a content excerpt. The browser loads this file and filters it with JavaScript.
For a blog with 50-100 posts, this JSON file is typically under 50KB. After the initial load, search is instant — pure client-side string matching with no network requests.
The downside is that you are building the search logic yourself. No fuzzy matching, no relevance ranking, no stemming. You get exact matches and substring matching. For a small site, that is usually enough.
Approach 2: Pagefind
Pagefind is a Rust-compiled-to-WASM search engine designed specifically for static sites. It indexes your content at build time and generates a small search bundle that runs in the browser.
- Bundle size: ~10KB JavaScript + ~75KB WASM (loaded on first search, not upfront)
- Ranking: BM25 algorithm, the same one used by Elasticsearch
- Features: Fuzzy matching, filtering by category, highlighting results
- Setup: Add a
data-pagefind-bodyattribute to your content wrapper, run the Pagefind CLI at build time
The setup is genuinely simple. If your site is built with any static generator, Pagefind probably has a plugin for it. The search quality is excellent — it handles typos, partial words, and relevance ranking out of the box.
Approach 3: Orama
Orama is an open-source full-text search engine written entirely in JavaScript. You build the index at deploy time using a Node.js script, serialize it to a JSON file, and restore it in the browser.
The bundled size is about 76KB — larger than Pagefind's WASM approach but loaded upfront. Orama supports fuzzy matching, vector search (semantic similarity), and complex queries with filters and facets.
For sites that need more than basic text search — faceted filtering, semantic search, complex boolean queries — Orama is the most flexible option.
The Comparison
| Approach | Size | Setup Effort | Features |
|---|---|---|---|
| JSON Index | ~50KB | 1 hour | Exact match, substring |
| Pagefind | ~85KB (lazy) | 30 minutes | Fuzzy, BM25, filtering |
| Orama | ~76KB | 2 hours | Fuzzy, vector, facets |
What About Other Libraries?
Lunr.js was the go-to for years but is effectively unmaintained since 2020. FlexSearch and MiniSearch are solid for custom implementations. Fuse.js does fuzzy matching but is designed for small datasets, not full-text search. For most static sites in 2026, Pagefind is the pragmatic choice — minimal setup, excellent results, zero external services.
Build-Time Index Automation
If you are using GitHub Actions, you can rebuild the search index on every push. Add a step to your deploy pipeline that runs the Pagefind CLI or your custom JSON generator. The search index stays fresh with zero manual effort.
The Recommendation
For a personal blog with under 200 posts, start with the JSON index approach. It takes an hour to build, adds zero dependencies, and gives you instant search. If you outgrow it — more posts, need fuzzy matching, or want better ranking — migrate to Pagefind. Both approaches keep your site fully static with no server dependencies.
The whole point of a static site is simplicity. Your search should be simple too.