Pagefind
Static-site search via WASM. Zero infrastructure. Perfect for Astro / Hugo / Eleventy sites.
VISIT PAGEFINDKey takeaway: If the site is static and the page count is in the thousands rather than the tens of thousands, Pagefind is not a compromise, it is the correct answer. Nothing to run, nothing to keep in sync, no bill. Step up to Typesense or Meilisearch only when you need server-side filtering, per-user results, or updates that cannot wait for the next build.
Quick facts
- CategoryEmbedded / static
- EngineRust / WASM
- PricingOpen source
- LicenseMIT
- Created2022
- GitHub stars4.4k
- Vector supportNo
- Edge-readyYes
What it is
Pagefind generates a search index at build time and ships it as WASM the browser fetches on demand. Zero server, zero ops, free forever. Works with any static site generator (Astro, Hugo, Eleventy, Jekyll, Next.js export). Drop-in instant search.
Best for
- Static / Jamstack sites with fewer than ~25k pages
- Documentation, blogs, marketing sites where adding any service is overhead
- Astro / Hugo / Eleventy / Jekyll deployments
- Cost-zero search where infrastructure spend is not justified
When not to pick it
Skip Pagefind past ~25k pages, index size grows and browser fetch cost rises. Skip if you need server-side filtering, real-time updates, or per-user personalisation.
My take
Pagefind is the right answer for static site search at small-to-mid scale. Zero ops is the differentiator. Past ~25k pages, graduate to Typesense or Meilisearch.
How the build-time index keeps the payload small
Pagefind runs after your build, crawls the emitted HTML rather than your source content, and writes a fragmented index alongside the site. That ordering matters. It indexes what visitors actually see, so anything your framework renders is searchable without you writing an extraction step, and it honours data-pagefind attributes when you need to exclude chrome or weight a region. At query time the browser loads a small WASM runtime plus only the index chunks the query touches, so a big site does not mean a big download. The cost model inverts the hosted engines: indexing is free at build time, queries are free at the edge because they are ordinary static file fetches from your CDN. For a documentation site or a blog on Astro, Hugo or Eleventy, that is the entire integration and there is no second system to keep alive.
The CSP and deployment traps nobody documents
Two things break Pagefind in production and neither produces a useful error. First, Content Security Policy. The runtime is WebAssembly executed inside a Web Worker, so your policy needs 'wasm-unsafe-eval' in script-src and 'self' blob: in worker-src. Without both, initialisation fails silently and the UI sits on its loading state forever. I lost an afternoon to exactly that on this site. Second, the index has to ship with the deploy. If your host prunes files outside the build output directory, or an asset pipeline rewrites hashed filenames, the runtime fetches chunks that are not there and you get empty results rather than an exception. Wire the Pagefind step into the build command itself instead of a separate CI job, and confirm the pagefind directory exists in the deployed output before you debug anything else.
Frequently asked questions
Is Pagefind free?
Completely. It is MIT-licensed, runs at build time, and serves queries as static file fetches from whatever CDN already hosts your site. There is no service, no account, no metered tier and nothing to expire. The only cost is a slightly longer build and the bytes of index that ship alongside your pages.
Does Pagefind work with Next.js?
With static export, yes: run Pagefind over the exported HTML as a post-build step and it works exactly as it does with Astro or Hugo. Server-rendered or dynamic App Router routes are not on disk at build time, so they will not be indexed. If most of your pages are dynamic, you want a real search service instead.
Why is my Pagefind search stuck on Searching?
Almost always Content Security Policy. Pagefind runs WebAssembly inside a Web Worker, so the policy needs 'wasm-unsafe-eval' in script-src and 'self' blob: in worker-src, and the failure is silent without them. The browser console names the directive that blocked it. The second most common cause is the pagefind directory missing from the deployed output.
Links
Compare Pagefind side-by-side
Similar tools you should also consider
If Pagefind is your pick, the next conversation is short
The 30-min call is where your search choice becomes a real architecture, a relevance-tuning plan, and a price range you can take to your stakeholders.