pagefind Documentation

Static low-bandwidth search at scale

5,371 stars Rust Rust 1 file Β· ~4,834 tokens
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy pagefind on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name pagefind -p 8080:8080 --restart always pagefind/pagefind:latest

File: README.md

Pagefind

Pagefind is a fully static search library that aims to perform well on large sites, while using as little of your users’ bandwidth as possible, and without hosting any infrastructure.

The full documentation on using Pagefind can be found at https://pagefind.app/.


File: docs/content/docs/components/_index.md


title: "Component System" nav_title: "Component System" weight: 2

The Pagefind Component UI is a set of web components that communicate through shared instances. This allows you to compose search interfaces from individual pieces, or use the prebuilt components that bundle everything together.

How Components Connect

Components on the same page automatically connect to each other. In this example, pagefind-input triggers searches, pagefind-summary shows the count, and pagefind-results displays the matches.

html

Named Instances

Use the instance attribute to create separate, independent search interfaces on the same page:

html

Components with the same instance value share state. Components with different instance values are completely independent β€” they maintain separate search terms, filters, and results.

Component Categories

Full Experiences

These components provide complete, ready-to-use search interfaces:

  • Modal β€” A dialog search with keyboard navigation. Supports custom inner structure
  • Modal Trigger β€” A button that opens the modal
  • Searchbox β€” A compact dropdown search

Building Blocks

These components can be composed together for custom layouts:

  • Input β€” The search text field
  • Results β€” The list of search results
  • Summary β€” Shows result count and search status
  • Keyboard Hints β€” Shows contextual keyboard shortcuts
  • Filter Dropdown β€” A dropdown to filter by a specific facet
  • Filter Pane β€” A sidebar-style filter panel with checkboxes

Configuration

  • Config β€” Set options for the Component UI, or for Pagefind itself

File: docs/content/docs/components/config.md


title: "" nav_title: "" nav_section: Components weight: 100

Declaratively configure a Pagefind instance. Optionally include this on the page to set options like bundle path.

html

Attributes

Attribute Type Default Description
bundle-path string auto-detected Path to Pagefind bundle files
base-url string "/" Base URL prepended to all result links
excerpt-length number 30 Length of result excerpts (in words)
lang string auto-detected Override the detected language for stemming and translations
instance string "default" Instance name to configure
preload boolean false Load Pagefind immediately instead of on first search
faceted boolean false Enable faceted search mode
highlight-param string β€” Add the search term as a query parameter under this key for use with the highlight script
exact-diacritics boolean false Treat diacritics as distinct characters instead of normalizing them
meta-cache-tag string β€” Replace the default cache-busting timestamp with a fixed string for offline/PWA support
no-worker boolean false Force Pagefind to run on the main thread instead of a web worker

Bundle Path Detection

By default, bundle-path is automatically detected from the location of the Pagefind script. If the script is loaded from /assets/pagefind/pagefind-component-ui.js, the bundle path defaults to /assets/pagefind/. If detection fails, it falls back to /pagefind/.

Important: Attributes Are Read Once

Attributes are only read when the component connects to the DOM. Changing attributes dynamically after connection has no effect. For dynamic configuration, use the JavaScript API instead.

Examples

Custom Bundle Path

When your Pagefind files are in a non-standard location:

html

External Bundle

Load from another domain:

html

Preload

Load Pagefind immediately on page load (instead of waiting for first search):

html

This improves perceived performance for search-only pages but adds initial page weight.

Faceted Search Mode

Enable faceted/browse mode for catalog-style interfaces where users filter content without requiring a search term:

html

When faceted is enabled:

  • Searching with an empty term returns all results (instead of showing nothing)
  • Results update immediately when filters are changed

Combine with preload to show all results immediately on page load. Without preload, results appear after the first user interaction (e.g., opening a filter dropdown).

Named Instance

Configure a specific instance:

html

Programmatic Configuration

For complex configuration, use JavaScript instead of the `` element:

html
<script>
  const { configureInstance } = window.PagefindComponents;

  configureInstance("default", {
    bundlePath: "/pagefind/",
    mergeIndex: [
      { bundlePath: "/other-site/pagefind/" }
    ],
    ranking: {
      termFrequency: 0.8
    }
  });
</script>

Either place this on the page as shown, or compile it into your existing JavaScript bundle.

See Pagefind Search Config for all available options.


File: docs/content/docs/components/filter-dropdown.md


title: "" nav_title: "" nav_section: Components weight: 90

A dropdown selector for a single filter.

html

Attributes

Attribute Type Default Description
filter string β€” Required. The filter key to display
label string filter name Text shown on the trigger button
single-select boolean false Allow only one selection (closes after selecting)
show-empty boolean false Show options with zero results
wrap boolean false Allow text to wrap to multiple lines
sort string "default" Sort filter values: default, alphabetical, count-desc, count-asc
hide-clear boolean false Hide the adjacent "Clear" button
instance string "default" Connect to a specific Pagefind instance

Keyboard Navigation

Full keyboard support following the ARIA Listbox pattern:

Key Action
↓ / ↑ Navigate through options
Home / End Jump to first/last option
Enter / Space Toggle selection
Escape Close dropdown
Tab Close and move focus
Type characters Jump to matching option (type-ahead)

Type-Ahead Behavior

When you type characters while the dropdown is open:

  • The component jumps to the first option that starts with the typed characters
  • Matching is case-insensitive
  • The type buffer clears after 500ms of inactivity

Faceted Search Mode

For catalog-style interfaces where users browse by filters without requiring a search term, enable faceted mode via ``:

html

In faceted mode, all results are shown initially and update immediately when filters are changed. See the config component documentation for details.


File: docs/content/docs/components/filter-pane.md


title: "" nav_title: "" nav_section: Components weight: 80

A full filter panel displaying all available filters. Filters automatically populate based on your indexed content.

html

Attributes

Attribute Type Default Description
show-empty boolean false Show filter options with zero results
expanded boolean false Always show groups expanded (non-collapsible)
open string "" Comma-separated filter names to start open
sort string "default" Sort filter values: default, alphabetical, count-desc, count-asc
auto-open-threshold number 6 Max values for auto-opening single groups (0 to disable)
instance string "default" Connect to a specific Pagefind instance

Auto-open Behavior

By default, filter groups are collapsible. If there is only one group, and it has options at or below the auto-open-threshold, it will open automatically.

Groups can also be opened by listing their keys in the open attribute.

Filter Visibility

  • Options with zero matching results are hidden by default (unless show-empty is set or the option is selected)
  • If all options in a group are hidden, the entire group is hidden

Faceted Search Mode

For catalog-style interfaces where users browse by filters without requiring a search term, enable faceted mode via ``:

html

In faceted mode, all results are shown initially and update immediately when filters are changed. See the config component documentation for details.


File: docs/content/docs/components/input.md


title: "" nav_title: "" nav_section: Components weight: 10

A search input field with debouncing.

html

Attributes

Attribute Type Default Description
placeholder string Language dependent Placeholder text shown when input is empty
debounce number 300 Milliseconds to wait after typing before searching
autofocus boolean false Focus input when page loads
instance string "default" Connect to a specific Pagefind instance

Behavior

  • Focusing the input begins loading the Pagefind search bundle
  • When search is triggered by other components, this input's value is automatically updated
  • When focused, the input registers keyboard shortcuts with the instance

Keyboard Behavior

Key Action
Escape Clear the input and reset search
↓ Move focus to the results list

File: docs/content/docs/components/keyboard-hints.md


title: "" nav_title: "" nav_section: Components weight: 50

Displays contextual keyboard shortcuts based on which component currently has focus.

html

Attributes

Attribute Type Default Description
instance string "default" Connect to a specific Pagefind instance

How It Works

Keyboard hints are contextual. Different components register their shortcuts when focused:

Component Focus Shortcuts Shown
Input ↓ navigate, esc clear
Results ↑↓ navigate, ↡ select, / search
Modal esc close

When no component has focus, the keyboard hints area is empty.

Accessibility

This component is marked aria-hidden="true" because it's a visual aid for sighted keyboard users.

The Component UI shortcuts are either the expected controls for WAI-ARIA patterns, or they are optional alternatives to standard tab navigation patterns.

Touch Devices

Keyboard hints are automatically hidden on touch-only devices.


File: docs/content/docs/components/modal.md


title: "" nav_title: "" nav_section: Components weight: 40

A modal overlay container for search. Opens over the page content and traps focus until closed. Users can close it by pressing Escape, clicking the backdrop, or using the close button in the header (visible on mobile).

html

Attributes

Attribute Type Default Description
reset-on-close boolean false Clear the search input when modal closes
instance string "default" Connect to a specific Pagefind instance

Default Structure

When used without child elements, the modal auto-generates a default structure:

html

If you want to customize the contents of your own modal, the above is a good starting point.

Structure Components

The modal uses three structural components. These are optional if you're providing your own modal contents, but it's recommended to place your components within them.

``

Fixed header area that stays pinned to the top of the modal. Typically contains the search input. Automatically includes a close button that is visible on mobile viewports.

``

Scrollable content area for results and other search content. Scroll is contained within this element so the header and footer remain visible.

``

Optional fixed footer area, pinned to the bottom of the modal. Typically contains keyboard hints or other supplementary information.


File: docs/content/docs/components/modal-trigger.md


title: "" nav_title: "" nav_section: Components weight: 60

A button that opens the associated modal.

html

Attributes

Attribute Type Default Description
placeholder string Language dependent Text shown on the trigger button
shortcut string "mod+k" Keyboard shortcut to open modal
hide-shortcut boolean false Hide the keyboard shortcut display
compact boolean false Show only the search icon, no text
instance string "default" Connect to a specific Pagefind instance

Keyboard Shortcut

By default, the trigger listens for Cmd+K (Mac) or Ctrl+K (Windows/Linux) to open the modal. The keyboard listener is attached at the document level, so the shortcut works from anywhere on the page.

Customizing the Shortcut

You can customize the keyboard shortcut using the shortcut attribute:

html

Example with / key:

Supported syntax:

  • Platform modifier: mod (Ctrl on Windows/Linux, Cmd on Mac)
  • Explicit modifiers: ctrl, shift, alt, cmd/meta
  • Keys: Any single character (e.g. k, /) or key name
  • Case-insensitive: Keys are normalized to lowercase

The shortcut display auto-detects the platform to show the correct modifier key (⌘ on Mac, Ctrl on other platforms).


File: docs/content/docs/components/results.md


title: "" nav_title: "" nav_section: Components weight: 20

Displays search results with automatic lazy loading. Results load their full data only when scrolled into view.

html

Attributes

Attribute Type Default Description
show-images boolean false Show/hide result images
hide-sub-results boolean false Hide anchor-based sub-results
max-sub-results number 3 Maximum number of sub-results per result
max-results number unlimited Limit number of results shown
link-target string β€” Set target attribute on result links (e.g., _blank for new tab)
instance string "default" Connect to a specific Pagefind instance

Keyboard Navigation

When results are focused, use these keys to navigate:

Key Action
↓ / ↑ Navigate between results
Enter Follow the selected link
Backspace Focus input and delete last character
/ Focus the search input
Any letter Focus input and type the character

Custom Templates

Customize result rendering using <script type="text/pagefind-template"> elements inside the component. Templates use a simple syntax with variables, conditionals, and loops.

Basic Template

html
<script type="text/pagefind-template">
    <li class="my-result">
      <h3>{{ meta.title }}</h3>
      [{{ url }}]({{ url | safeUrl }})
      {{+ excerpt +}}
    </li>
  </script>

Your template must have a single root element (e.g. a single <li>). Keyboard navigation moves between <a> elements in the results list, so ensure your main result link is an <a> tag.

The full templating syntax can be seen in the adequate-little-templates package.

Available Data

Templates receive this data structure:

Field Description
meta.title Page title
meta.url Page URL
meta.image Page image (if set)
meta.image_alt Image alt text
meta.* Any custom metadata
excerpt Search excerpt with <mark> highlighting (use {{+ excerpt +}})
url Fallback URL
sub_results Array of matching sections within the page
options.* The attributes supplied to the `` element

Each sub-result has: title, url, excerpt.

Template Filters

The template engine provides built-in filters. The Component UI registers the following additional filters:

`resolveUrl(pageUrl)`

Resolves a relative URL against a page URL. Absolute URLs are returned unchanged.

text
"images/hero.png" | resolveUrl("/blog/post/")  β†’  /blog/post/images/hero.png

Placeholder Template

While results are loading, a skeleton placeholder is shown. You can customize it with a second template using data-template="placeholder", as shown in the full example below. The placeholder template receives no data β€” it is static HTML.

Full Template Example

Here's the built-in template. Copy and customize it:

html
<script type="text/pagefind-template">
    <li class="pf-result">
      
        {{#if and(options.show_images, meta.image)}}
        
        {{/if}}
        
          
            <a class="pf-result-link" href="{{ meta.url | default(url) | safeUrl }}"{{#if options.link_target}} target="{{ options.link_target }}"{{/if}}{{#if eq(options.link_target, "_blank")}} rel="noopener"{{/if}}>{{ meta.title }}</a>
          
          {{#if excerpt}}
          {{+ excerpt +}}
          {{/if}}
        
      
      {{#if sub_results}}
      
        {{#each sub_results as sub}}
        <li class="pf-heading-chip">
          <a class="pf-heading-link" href="{{ sub.url | safeUrl }}"{{#if options.link_target}} target="{{ options.link_target }}"{{/if}}{{#if eq(options.link_target, "_blank")}} rel="noopener"{{/if}}>{{ sub.title }}</a>
          {{+ sub.excerpt +}}
        </li>
        {{/each}}
      
      {{/if}}
    </li>
  </script>
  <script type="text/pagefind-template" data-template="placeholder">
    <li class="pf-result" aria-hidden="true">
      
        
        
          
          
        
      
    </li>
  </script>

Results Layout

By default, results display in a single column. You can change the layout of the results container using CSS variables, for example a grid layout:

css
:root {
    --pf-results-display: grid;
    --pf-results-columns: repeat(auto-fill, minmax(250px, 1fr));
    --pf-results-gap: 16px;
}

See CSS Variables for all available layout variables.