Patrick Müller • 4/25/2026 • 2 min read

Pagefind, Astro and React

Want to use Pagefind in an Astro + React blog with custom components? In this post, I show how I replaced the default search UI by integrating pagefind.js directly into my Astro layout and React components. I also cover GitHub Actions indexing and multilingual support for Astro projects.

The Astro logo on a dark background with a pink glow.

Integrating Pagefind into an Astro + React Blog with Custom Components

Using Pagefind with its predefined search component is pretty easy. If you want a quick setup, you can use the npm package astro-pagefind.

Astro-Pagefind Quick Tutorial

Install

npm install astro-pagefind

Setup

import { defineConfig } from "astro/config";
import pagefind from "astro-pagefind";

export default defineConfig({
  integrations: [pagefind()],
});

Usage

Use the built-in search component in your Astro pages.

Pros

  • Fast setup
  • Easy integration
  • Works great with plain Astro

Cons

  • Limited customization
  • Not ideal for React-based UI

Why Use Pagefind.js Directly?

If your site uses Astro + React and custom components, the predefined component can be limiting.

So instead, you can integrate pagefind.js directly.


BaseLayout.astro Setup

Initialize Pagefind globally in your layout:

<script is:inline>
  const pagefind = await import("pagefind/pagefind.js");

  await pagefind.init();

  window.pagefind = pagefind;
</script>

Now Pagefind is available inside React components via:

window.pagefind

Example React Component

import { useState } from "react";

export default function Search() {
  const [results, setResults] = useState([]);

  async function handleSearch(query) {
    if (!query) return;

    const search = await window.pagefind.search(query);

    const data = await Promise.all(
      search.results.map((r) => r.data())
    );

    setResults(data);
  }

  return (
    <div>
      <input
        placeholder="Search..."
        onChange={(e) => handleSearch(e.target.value)}
      />

      <ul>
        {results.map((item, i) => (
          <li key={i}>
            <a href={item.url}>{item.meta.title}</a>
          </li>
        ))}
      </ul>
    </div>
  );
}

GitHub Actions / GitHub Pages

After building Astro, run:

npx pagefind --site dist

Example:

{
  "scripts": {
    "build": "astro build && npx pagefind --site dist"
  }
}

Multi-language Support

In your shared layout:

<html lang="en">

or

<html lang="de">

This helps Pagefind index content correctly.


Final Thoughts

If you use plain Astro, astro-pagefind is easiest.

If you use Astro + React with custom UI, using pagefind.js directly gives full control.