Making Pagefind Work in Astro Development
Why Pagefind can work in an Astro production build but fail during local development, and a small build-first workflow that keeps both environments predictable.

Photo by MJ Duford on Unsplash.
The search page looked finished: the input rendered, the colors followed the site theme, and the results panel had enough room for useful excerpts. Then the browser console repeated one message:
Pagefind Error: Could not load search bundle
Bundle path: /pagefind/
The path was correct. The bundle simply did not exist yet.
That distinction is the key to using Pagefind with Astro. Pagefind does not crawl Markdown source files or query Astro’s content collection at runtime. It indexes the static HTML produced by a build, then writes a browser-side search bundle. A normal development server can render the search interface before that bundle has ever been generated.
The production path is straightforward
For a static Astro site, the production script can build the HTML first and run Pagefind second:
{
"scripts": {
"build": "astro build && pagefind --site dist"
}
}
After astro build, the dist directory contains the rendered pages. Pagefind reads those files and creates dist/pagefind, which is deployed with the rest of the site.
The search component can then point at the public URL:
<pagefind-config bundle-path="/pagefind/" lang="en" />
<pagefind-input placeholder="Search articles" />
<pagefind-results></pagefind-results>
This works in production because /pagefind/ is present in the final deployment artifact.
Why astro dev behaves differently
astro dev serves pages from the project source. It does not need to populate dist, and it does not automatically run a tool that depends on completed HTML.
The search UI therefore asks the development server for files such as:
/pagefind/pagefind.js
/pagefind/pagefind-entry.json
If those files are absent from public/pagefind, the component cannot initialize. Changing the bundle path only changes where the missing files are requested; it does not create an index.
A small development workflow
For this blog, the practical solution is a predev script:
{
"scripts": {
"predev": "astro build && pagefind --site dist --output-path public/pagefind --quiet",
"dev": "astro dev",
"build": "astro build && pagefind --site dist"
}
}
Running npm run dev now does three things in order:
- Astro creates a fresh static build in
dist. - Pagefind indexes that build and writes the development bundle to
public/pagefind. - Astro starts the development server, which exposes everything in
publicat the site root.
The generated development bundle should not be committed:
public/pagefind/
Production remains clean: the regular build writes its own index inside dist, so deployment does not depend on a generated local directory.
The trade-off: the local index is a snapshot
This approach generates the index once, before the development server starts. Editing an article updates the page immediately, but search results still reflect the pre-start snapshot.
For a small blog, restarting npm run dev after adding or renaming an article is usually enough. Other reasonable options are:
- test search against
npm run build && npm run preview; - run Pagefind again manually when content changes;
- build a file watcher if instant search-index updates are genuinely important.
A watcher adds moving parts, so it is worth asking whether search needs hot reload at all. The page layout usually does; the index often does not.
A quick diagnostic checklist
When the bundle error appears, check the pipeline in this order:
- Was the site built? Pagefind needs rendered HTML.
- Did Pagefind index the correct directory? For Astro’s default static output, that directory is
dist. - Where did Pagefind write its files? Development and production may intentionally use different filesystem locations.
- What public URL does the component request?
bundle-path="/pagefind/"must match the URL served by Astro or the host. - Is the generated local bundle ignored by Git? Search indexes are build artifacts, not source content.
The useful mental model is simple: the component is only the interface. The searchable data appears after Pagefind has seen a completed site build.
