This guide shows how to add full-text search to Astro’s default blog template using Pagefind.
Pagefind indexes your built static HTML files and generates a static search bundle that can be served directly from your site. No external search service or backend is required.
Install Pagefind
Install Pagefind:
npm install -D pagefind
This adds Pagefind to your project, usually under devDependencies:
{
"devDependencies": {
"pagefind": "^1.5.2"
}
}
Generate the Pagefind index
Pagefind must run after Astro builds your site, because it indexes the generated HTML inside dist/.
Update your build script:
{
"scripts": {
"dev": "astro dev",
"build": "astro build && pagefind --site dist --output-subdir pagefind",
"preview": "astro preview"
}
}
This command tells Pagefind to:
- index the built site in
dist/ - write the generated search files to
dist/pagefind/
After a successful build, these files should be available from your deployed site:
https://your-domain.com/pagefind/pagefind-component-ui.js
https://your-domain.com/pagefind/pagefind-component-ui.css
https://your-domain.com/pagefind/pagefind-entry.json
Include the stylesheet and script
Add the Pagefind Component UI assets to src/components/BaseHead.astro:
<!-- Pagefind Component UI -->
<link href="/pagefind/pagefind-component-ui.css" rel="stylesheet" />
<script is:inline src="/pagefind/pagefind-component-ui.js" type="module"></script>
Keep is:inline on this script tag. The file /pagefind/pagefind-component-ui.js is not inside Astro’s src/ folder. It is generated inside dist/pagefind/ after Pagefind runs.
Astro normally processes scripts it finds in components by bundling, optimizing, resolving imports, and deduplicating them. is:inline tells Astro to leave this script tag exactly as written in the final HTML.
The default Astro blog template imports BaseHead.astro into its layouts, so adding the Pagefind assets there makes the Component UI available across the site.
Example layout usage:
---
import BaseHead from '../components/BaseHead.astro';
const { title, description } = Astro.props;
---
<html lang="en">
<head>
<BaseHead title={title} description={description} />
</head>
<body>
<slot />
</body>
</html>
If you create a new layout where the search UI should appear, make sure that layout also includes BaseHead.
Add the search button
Add the Pagefind modal trigger wherever you want the search button to appear. For example, you can place it inside src/components/Header.astro:
<div class="search-button">
<pagefind-config bundle-path="/pagefind/"></pagefind-config>
<pagefind-modal-trigger></pagefind-modal-trigger>
<pagefind-modal></pagefind-modal>
</div>
The pagefind-config element tells the Component UI where to find the generated Pagefind bundle:
<pagefind-config bundle-path="/pagefind/"></pagefind-config>
This must match the output directory from your build command:
pagefind --site dist --output-subdir pagefind
Pagefind can usually auto-detect this path from the script URL, but setting it explicitly avoids issues with some static hosts, CDNs, and rewrite rules.
Test the search locally
Run:
npm run build
npm run preview
Then open the preview site and test the search button.
Do not expect search to work from npm run dev unless the generated Pagefind files already exist and are being served. Pagefind indexes the built output, so the normal flow is:
npm run build
npm run preview
Control what Pagefind indexes
By default, Pagefind indexes content from the page body. You can narrow the indexed content by adding data-pagefind-body to the part of the page you want indexed.
For blog posts, a good place is usually src/layouts/BlogPost.astro:
<Header />
<main data-pagefind-body>
<article>
<slot />
</article>
</main>
This tells Pagefind to index the blog post content and ignore surrounding layout content such as navigation, sidebars, and footers.
Important: once Pagefind finds data-pagefind-body anywhere on your site, pages without that attribute will not be indexed. If you want your homepage or other pages to appear in search results, add data-pagefind-body to those pages too.
For more indexing options, see the official Pagefind documentation on configuring indexed content.