Implement full-text search in your Astro blog in 15 minutes

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.

Sources