Tools

Site Search Without a Backend: What You Ship vs What You Call

Search on a static site is a solved problem with an unsolved decision attached. The tools exist and they work; what varies is where the index lives, and that choice determines your bundle size, your dependency on a third party, and whether your site still works with JavaScript disabled.

Two architectures

Ship the index. The search index is built at the same time as the site and delivered as static files. The browser downloads what it needs and searches locally. No network round trip per query, no service to be down, no data leaving the visitor’s machine.

Call a service. The query goes to an API. The index lives on someone else’s infrastructure. Small bundle, better relevance tuning, and a dependency you do not control.

Every tool in this space falls on one side, and the choice is architectural before it is a product choice.

What each option documents

ToolWhere the index livesLicenceDocumented character
PagefindStatic files, built after the site buildMIT“Static low-bandwidth search at scale”
LunrShipped to the browserMITClassic client-side full-text library
MiniSearchShipped to the browserMITFor data that “can fit locally in the process memory”
FlexSearchShipped, or a persistent backendApache-2.0Browser and Node, with storage backends
DocSearch (Algolia)Third-party service, free for eligible sitesFor public technical documentation

Note the licences, because two are permissive in the same way and one is not the same category. MIT and Apache-2.0 are both fine for commercial use; Apache-2.0 adds an explicit patent grant, which matters to some legal teams and not to others.

Pagefind, and why “built after the build” is the interesting part

Pagefind’s architecture is documented and unusual: it runs after your static build, reads the generated HTML, and produces a static search bundle as an output. The documentation states plainly that “Pagefind itself does not have any server component — the search integration is fully baked into your static site.”

That has three practical consequences:

It indexes what you actually ship. Not your Markdown source, not your front matter — the rendered HTML. If your build generates a table of contents, Pagefind sees it. If your build strips something, Pagefind does not see it.

It leaves your build pipeline alone. It is a post-build step, so it works with any generator. The documented invocation is a one-line command pointed at your output directory, and installation is available through several package managers as well as a standalone binary.

It is chunked. The build reports statistics like pages indexed and index chunks created, and the documented scaling mechanism is that the index is split into chunks which are loaded lazily. That answers the obvious objection — a single monolithic index would grow linearly and eventually be absurd to download — without the documentation needing to state a size limit, which it does not.

The honest limitation for this site: I could not verify a claim about index size, a size-to-content ratio, or an explicit statement about JavaScript requirements from Pagefind’s documentation. The integration is a module script plus WebAssembly, which strongly implies JavaScript is required — but that is an inference from the integration, not a documented statement. Do not repeat it as a quoted fact.

Self-hosting search means shipping JavaScript

This is the trade-off that a zero-JS site has to face directly, and it is not a tool limitation — it is arithmetic. A local index has to be queried by something that runs in the browser. There is no server to query it for you.

So a site that currently ships no JavaScript has three options:

  1. Add a JavaScript dependency for search only. Accept it, lazy-load it, and make sure the search UI is progressive — a plain link that works without the script.
  2. Move search server-side. Either a service, or a function that queries an index you host. This keeps the page JS-free at the cost of a runtime.
  3. Skip search. Below a few hundred pages, a well-organised index page and a sitemap may genuinely be enough.

The third option is underrated. The documentation for one major search provider states that a site that is “small” — around 500 pages or fewer — may not need a sitemap for discovery. If several hundred pages do not need a sitemap, they may not need search either.

The service option, and its documented eligibility

If you go the other way, the well-known free tier has documented criteria: the programme is “open to developer documentation and technical blogs,” and applications are “usually turned down… when they are not production ready or have non-technical content.”

There is also a process with timing attached: domain verification within a week, then manual review. Worth knowing if you were planning to launch with search on day one.

The trade-offs of a service are the obvious ones: queries leave your site, the service can be down or change its terms, and the free tier has eligibility rules you may fall outside of. The gains are relevance quality and zero bundle cost.

The decision, in practice

SituationReasonable choice
Under ~100 pages, well-organisedNo search; improve the index page
Content site, a few hundred pagesClient-side index, lazy-loaded with a no-JS fallback link
Documentation site, technical audienceConsider the free service tier — that is what it is for
You refuse to ship JSServer-side search behind a function, or no search
Very large siteChunked client-side index, or a hosted service

What to actually measure before choosing

Two numbers, both measurable on your own site:

How many pages are there, and how large is the rendered text of one? Multiply. That gives you the raw text volume a client-side index has to represent. It is not the index size — compression and tokenisation change that — but it tells you the order of magnitude and whether the idea is reasonable at all.

How much of your traffic would use search? If you have analytics, you may already know. A site where readers arrive from search engines and read one article has a different search need from a site where readers browse a reference.

Run those two numbers before evaluating tools. If the answer is that search would serve a small minority of visits, the cost — a JavaScript dependency on every page that mounts the search UI, or a third-party service — may exceed the benefit, and the honest choice is to make the index page better.

One thing that applies to all of them

Whatever you choose, check what the index contains. A client-side index built from your rendered HTML includes everything in the HTML — navigation, footers, sidebar links, and any content you thought was hidden. Pagefind works from the built output, which means your templates are part of the corpus.

The fix is scope: index the article body, and exclude the chrome. Most tools provide a way to mark or exclude regions, and it is worth configuring on the first day rather than after your search results start returning the same navigation links for every query.


Written by TestedHost. Every recommendation on this site comes from running the setup described, on a live deployment — not from a vendor spec sheet. Spotted something out of date? Tell us.