A search index dropped into the build output
Pagefind is a full-text search library for static sites, written in Rust and released under the MIT license. Once the site generator has finished, its binary reads the HTML in the output folder and adds a pagefind/ directory: the index, split into chunks, plus the JavaScript that queries it in the browser. There is no search server to host, and the deployed site is still plain files.
Chunks fetched per query, settings kept in the markup
- Payload: the docs put a search on a 10,000-page site at under 300 kB of network transfer, library included, and closer to 100 kB on most sites. The browser only fetches the chunks a query needs, and 1.5.0 made them about 45% smaller.
- Template attributes:
data-pagefind-*attributes (body,ignore,meta,filter,sort) mark what gets indexed and declare metadata, facets and sort keys. - One index per language: Pagefind reads the
langattribute on<html>, indexes each language on its own and only searches the language of the current page. Stemming applies wherever that language is supported. - Accent-insensitive matching: since 1.5.0, "cafe" finds "café" with exact spellings ranked first. Setting
exactDiacritics: truebrings back strict matching. - Section-level hits: any
h1toh6heading with anidbecomes a sub-result that links straight to that anchor. - Web component UI: 1.5.0 added
<pagefind-*>elements (modal, dropdown searchbox, filters) styled through CSS variables and translated to the page language. A JavaScript API is still there for a fully custom interface.
SSG sites, PDFs and cross-domain search
- Adding search to a Hugo, Zola, Astro or Eleventy site: the community resources page lists a guide or an integration for each one.
- Indexing PDFs or subtitles through the Node or Python API:
addCustomRecordtakes a URL, a language and the raw text, which the calling script has to extract first. - Searching a blog and its docs across two domains from one box:
mergeIndexcombines the indexes in the browser, as long as the other domain sends CORS headers.
Reindexing on every build, and wasm in the CSP
The index is built from the final HTML. Under hugo serve or any other dev server, search does not show up until Pagefind has indexed the output folder, so the command belongs in the deploy pipeline after every build.
A strict Content Security Policy breaks search. The docs ask for script-src 'wasm-unsafe-eval' to let the WebAssembly run and, where workers are restricted, worker-src 'self' blob:. Setting noWorker: true moves search back to the main thread.
A single data-pagefind-body narrows the whole site. Once any page carries the attribute, every page without it drops out of the index, homepage included.
Chinese, Japanese and Korean need the extended build. The larger pagefind_extended binary segments these languages but does not stem them; npx pagefind downloads it by default, while pip needs pagefind[extended]. Czech, Ukrainian and Vietnamese have no stemming either, so a query will not match other forms of the same word.
The stated target is sites with tens of thousands of pages. That goal is spelled out in the docs, which link to demo searches over MDN, Godot and XKCD. Pagefind has no server component: --serve only starts a static preview server.
The latest release is v1.5.2, from April 12, 2026. The project has been on 1.x since September 2023, and the last commit landed on October 26, 2026. The older Default UI and Modular UI are still supported "for now", according to the 1.5.0 release notes.
