Tech 2 min read

Adding Full-Text Search to an Astro Static Site with Pagefind

IkesanContents

One weakness of static sites is search. Without a server-side backend, you either rely on an external service or build something yourself.

I added Pagefind to this blog, so this is a note on how I did it.

What Pagefind Is

Pagefind is a full-text search library for static sites.

Features:

  • Crawls HTML at build time and generates an index
  • Splits the index into small chunks so only needed parts are fetched
  • Fast search via WebAssembly
  • Supports Japanese
  • No external service required

Even with 1,000 pages, the initial load stays around a few dozen KB.

Installation

For Astro, there is an integration called astro-pagefind.

pnpm add astro-pagefind @pagefind/default-ui

Add it to astro.config.mjs:

import pagefind from 'astro-pagefind';

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

Creating the Search Page

---
import BaseLayout from '@/layouts/BaseLayout.astro';
---

<BaseLayout title="Search" description="Search articles">
  <main>
    <h1>Search</h1>
    <div id="search"></div>
  </main>
</BaseLayout>

<script>
  import { PagefindUI } from '@pagefind/default-ui';
  import '@pagefind/default-ui/css/ui.css';

  new PagefindUI({
    element: '#search',
    showSubResults: true,
    translations: {
      placeholder: 'Search articles...',
      zero_results: 'No articles matched "[SEARCH_TERM]"',
    },
  });
</script>

Customizing the Style

Pagefind’s UI can be customized with CSS variables.

<style is:global>
  :root {
    --pagefind-ui-scale: 1;
    --pagefind-ui-primary: hsl(var(--primary));
    --pagefind-ui-text: hsl(var(--foreground));
    --pagefind-ui-background: hsl(var(--background));
    --pagefind-ui-border: hsl(var(--border));
    --pagefind-ui-tag: hsl(var(--secondary));
    --pagefind-ui-border-width: 1px;
    --pagefind-ui-border-radius: 0.5rem;
    --pagefind-ui-font: inherit;
  }
</style>

You can reuse the existing design-system variables as-is.

Caveats

It Does Not Work in the Dev Server

Search does not work with pnpm dev. Pagefind’s index is generated during pnpm build.

Use pnpm preview after building to verify it.

Impact on Build Time

Pagefind’s index generation is light. Even a few hundred pages only add a few seconds. It is fine even on Vercel’s free plan.

On this blog (about 80 pages), it took around 0.4 seconds.

Summary

  • Install astro-pagefind and @pagefind/default-ui
  • Create a search page and initialize PagefindUI
  • Customize the style with CSS variables
  • Use pnpm preview when testing

Full-text search without an external service is very convenient.