The Static Search Plugin
Static Search adds browser-based search to your Publii site using the FlexSearch library. Visitors can search posts, pages, and tags, with results updating as they type and optional highlighting of matching text. You control which content is indexed, how searches match words, and how the search popup looks. You can also combine results from several Publii sites. Other search options include Google Custom Search and DocSearch.
Enabling the search section
If your theme includes a search option, enable it before configuring the plugin:
- Open Theme in Publii's left sidebar.
- Under Custom settings, open the Search tab.
- Enable the Search option.
The location of this setting can vary by theme. You can also open the search popup from an existing button or link using the plugin's CSS selector setting.
Adding support to an older or custom theme
To add the plugin's search field to a theme, place the following Handlebars expression in the template where the field should appear, such as partials/navbar.hbs or partials/header.hbs:
{{{@customSearchInput}}}This expression belongs in a theme template. Adding it to the content of a post or page will not create the search field.
With the default Publii storage location, your site's theme files are in:
Documents ▸ Publii ▸ sites ▸ YOUR_SITE ▸ input ▸ themes ▸ YOUR_THEMEThe expression renders a search input and, if enabled in the plugin settings, a submit button. Its appearance depends on the theme's styles.
If the theme does not already support search plugins, merge these flags into the existing renderer and supportedFeatures sections of its config.json. Keep the other settings in those sections:
"renderer": {
"createSearchPage": false,
"createContentStructure": true
},
"supportedFeatures": {
"searchPage": true,
"customSearch": true
},Enabling the plugin
Open Tools & Plugins in Publii and enable the switch on the Static Search tile. Then click the tile to open its settings.
Choose the content you want visitors to search, adjust the labels and options, and save your changes. Preview the site to check the search, then synchronize it to publish the updated files.
Static Search options
Search configuration
- Open a search popup when clicking search input: Opens the popup as soon as a visitor clicks the theme's search field. Otherwise, the visitor submits the form to open it.
- Open a search popup by CSS selector: Lets you use an existing element, such as a search icon, button, or link, to open the popup. Enter its selector in the field below.
- CSS selector: The selector for your search trigger. For example, use
.search-popupfor<button class="search-popup">Open search popup</button>. - Submit button: Adds a button to the theme's search form. Visitors can also submit the form by pressing Enter.
- Minimum character count to trigger search: Sets how many characters visitors must enter before a search runs. If you change this value, update the “phrase is too short” message to match.
- Maximum number of search results: Sets the result limit. With highlighting enabled, the limit applies separately to title and content matches, so the combined list can contain more results.
- Show description in results as: Selects the text displayed below each result title:
- None: Displays titles without descriptions.
- Excerpt: Displays post and page excerpts, or tag descriptions. Excerpt length depends on your theme settings and any custom excerpt defined in the content.
- Meta Description: Displays the item's meta description.
Enable indexing of the selected description field so that its text is available. When highlighting searches all indexed fields, matching content from another field can appear in this area.
- Search input placeholder: Placeholder text in the theme's search field.
- Search button label: Text on the theme's search submit button.
- Popup search input placeholder: Placeholder text in the popup's search field.
- Search empty state: Message shown before visitors enter a query.
- Text displayed when phrase is too short: Message shown when the query has fewer characters than the configured minimum.
- No results state: Message shown when a completed search finds no matches.
- Search loading error: Message shown if no search source can be loaded. Visitors can close and reopen the popup to try again.
- Close button: Label for the button that closes the popup.
Index configuration
These settings control which content the plugin collects for searching. The plugin indexes selected fields, such as titles, excerpts, and headings. It does not automatically index the entire body of every post and page.
Note: More indexed fields make more content searchable, but also increase the amount of data visitors download and process. For a large site, enable the fields visitors need. GZIP or Brotli compression on your server can reduce the download size.
Posts
- Enable Posts indexing: Includes posts in the search index.
- Exclude hidden posts: Excludes posts marked as hidden.
- Post title: Includes post titles in searches.
- Excerpt: Includes post excerpts. Their length depends on the Excerpt length setting in Theme Settings > Basic settings, or the custom excerpt defined by the read-more position.
- Headings (H1-H6): Includes headings from post content.
- Author name: Allows visitors to find posts by author name.
- Meta description: Includes post meta descriptions.
Pages
- Enable Pages indexing: Includes pages in the search index.
- Page title: Includes page titles in searches.
- Excerpt: Includes page excerpts.
- Headings (H1-H6): Includes headings from page content.
- Meta description: Includes page meta descriptions.
Tags
- Enable Tags indexing: Includes tags in the search index.
- Exclude hidden tags: Excludes tags marked as hidden.
- Tag name: Includes tag names in searches.
- Tag description: Includes tag descriptions.
- Meta description: Includes tag meta descriptions.
Custom configuration fields
Enable Post Config indexing and Enable Page Config indexing let you include selected configuration fields defined by your theme. In the corresponding Fields to index box, enter the field names separated by commas, for example subtitle,location.
When result highlighting is enabled, titles remain searchable and the Highlighting search scope setting controls which other fields are searched. See the options below.
Advanced options
Tokenize option value
This setting controls how much of a word visitors need to type. Forward, the default, is a useful starting point for searches that update as visitors type. Broader tokenization uses more memory in the visitor's browser.
- Strict: Matches complete terms after the selected Charset and Language processing.
- Forward: Matches words from the beginning. For example,
tescan match “testing”. - Reverse: Matches prefixes and suffixes. For example,
tesandingcan match “testing”. - Full: Also matches parts within a word. For example,
stican match “testing”.
Charset
Charset selects how FlexSearch normalizes words before matching them. The default latin, also available as LatinDefault, is a starting point for Western European languages. latin:extra, also available as LatinExtra, provides broader matching and is recommended for Polish and other Central and Eastern European languages.
Recommended starting points:
| Charset | Languages |
|---|---|
latin | English, German, French, Spanish, Italian, Dutch, Portuguese, Norwegian, Swedish, Finnish, Icelandic, Afrikaans, Indonesian, Malay |
latin:extra | Polish, Czech, Slovak, Slovenian, Croatian, Romanian, Hungarian, Turkish, Estonian, Latvian, Lithuanian, Albanian |
Test a few common queries from your own content when choosing a preset. For example, latin:extra can match “modlitwa” with “modlitwy”. Broader matching can also return less relevant results. Other available presets include Normalize, Exact, LatinBalance, LatinAdvanced, LatinSoundex, and CJK for Chinese, Japanese, and Korean.
Language
Language adds language-specific word processing, including stemming and stop-word filtering. Stemming can match different forms of a word; stop-word filtering removes common words from searches.
The plugin includes modules for en (English), de (German), and fr (French). Regional codes such as en-GB, de-DE, and fr-FR select the corresponding language module. The default is en-GB. You can consult this language code reference for code formats; the plugin supports the three modules listed here.
For Polish and other languages without a bundled module, leave this field empty and choose a suitable Charset. Entering an unsupported code, such as pl, also uses the selected Charset without adding language-specific stemming.
Enable cache
This option stores search results in memory so repeated queries can reuse them while the page is open. The cache belongs to the current visitor's page session. It is rebuilt when the search index is reloaded.
- Disabled: Runs each query without storing its results in the query cache.
- Enabled - no size limit: Stores query results without a configured entry limit.
- Enabled - with size limit: Limits the number of cached queries. Older entries are removed as the cache fills.
Cache size is available for the limited mode and defaults to 100. With highlighting enabled, the limit applies separately to the title and content search caches. Browser caching of downloaded index files is handled separately.
Enable suggestions
This option allows results that match only some of the words in a multiword query. For example, a query for “alpha gamma” can return an item containing “alpha beta”. Suggestions are based on indexed content; the plugin does not collect popular queries or show an autocomplete list.
Enable result highlighting
Highlights matching text in result titles and descriptions. Use Highlighting search scope to choose which content is searched while this option is enabled:
- All indexed fields: Searches titles and the enabled content fields, including excerpts, headings, authors, meta descriptions, and custom configuration fields. If descriptions are displayed, highlighted content can include text from these fields.
- Title and description only (default): Searches titles and the description selected in Show description in results as. If descriptions are set to None, only titles are searched.
The selected scope affects which results can be found. For example, a word that appears only in a heading will not be found with Title and description only, even when heading indexing is enabled. Changing the scope or switching highlighting on or off can change the results.
Relative URLs - domain
If your site uses relative URLs in the server settings, enter its public base URL here so the search index contains links that work outside the original page. Include the site's subdirectory if needed, and omit the trailing slash, for example https://example.com/blog.
Note: This is especially useful when another site's search will include this index. Configure the base URL on each source site that uses relative URLs.
Additional index sources
Use this field to combine results from other Publii sites with the current site's results. Enter the URL of each site's Static Search index.js, separated by new lines or commas. The local index is included automatically.
/blog/media/plugins/staticSearch/index.js
/docs/media/plugins/staticSearch/index.jsThese example paths refer to sites in the /blog and /docs subdirectories of the same domain. You can also use complete HTTPS URLs. Start same-domain paths with / so they resolve consistently from nested pages.
Each source must have Static Search enabled and its index published. Its own indexing settings determine which data it supplies. Search settings on the site displaying the popup then control how that data is searched. Use sources you manage or trust, because their index files load as JavaScript.
Repeated source addresses are ignored. Matching record IDs from different sites are handled separately, so one site's post does not replace another site's post. Result links use the URLs supplied by each source.
Updating the search index
When Publii generates your site, Static Search updates the search data and a small file that identifies its current version. The popup checks that version whenever it opens and requests the corresponding index. If the index has not changed, the browser can reuse its cached copy.
This means an edit to indexed content no longer changes the search code embedded in every page. The first publication after installing this update changes that code once. Later content changes update the affected pages and search files; changes to your theme or other site-wide settings can still require additional files to be uploaded.
For example, changing an H2 updates search data when heading indexing is enabled. To find text that appears only in that heading with highlighting enabled, select All indexed fields.
Older additional sources without a version file remain supported. Their indexes are requested with a fresh URL parameter when the popup opens. If you use a custom CDN cache policy, ensure it includes URL query parameters in its cache key.
If a popup is already open during a site update, close and reopen it to check for the latest index.
If search cannot load
If one additional source fails, the popup still searches the sources that loaded successfully. If none can be loaded, it displays the message configured under Search loading error. Close and reopen the popup to retry.
Check that each configured index URL is published and accessible. A source that loads successfully but contains no matching content produces the normal No results state message.
Customizing the plugin's appearance
The theme's search form
The plugin renders the form wherever your theme includes {{{@customSearchInput}}}. With the submit button enabled and the default labels, the output has this structure:
<form action="#search" class="search__form">
<input class="search__input" type="search" placeholder="Search" aria-label="Search">
<button type="submit" class="search__button">
<span>Search</span>
</button>
</form>Use the search__form, search__input, and search__button classes to style the form to match your theme.
The search results popup
You can adjust the popup using the Custom CSS tool in Tools & Plugins. Override the variables you need from the following list, or copy the full block as a starting point.
--pss-highlight-bg sets the background behind matching text. --pss-highlight-hover controls that text highlight on a hovered result. --pss-results-highlight-bg controls the background of the hovered result row.
Available CSS variables
:root {
--pss-width: 672px;
--pss-popup-min-height: 210px;
--pss-popup-max-height: 576px;
--pss-popup-input-height: 70px;
--pss-border-radius: 4px;
--pss-spacing: 20px;
--pss-font-base-size: 15px;
--pss-font-family: inherit;
--pss-results-title-font-weight: 500;
--pss-results-excerpt-line-height: 1.2;
--pss-bg: #fff;
--pss-overlay: rgba(184, 186, 193, 0.9);
--pss-border-color: #e7e8ea;
--pss-color: #0079f2;
--pss-msg-text-color: #6A7082;
--pss-input-bg: #fff;
--pss-input-text-color: #32353e;
--pss-input-placeholder-color: #7f8596;
--pss-button-close-bg: #6A7082;
--pss-button-close-color: #fff;
--pss-results-title-color: #32353e;
--pss-results-title-color-hover: #fff;
--pss-results-excerpt-color: #6A7082;
--pss-results-excerpt-color-hover: #fff;
--pss-results-icon-color: #969faf;
--pss-results-icon-color-hover: #fff;
--pss-results-highlight-bg: #0079f2;
--pss-highlight-bg: rgba(255,213,0,0.4);
--pss-highlight-hover: rgba(255,255,255,0.25);
}
@media (prefers-color-scheme: dark) {
:root {
--pss-bg: #191a1f;
--pss-overlay: rgba(10, 10, 12, 0.8);
--pss-border-color: #2A2B34;
--pss-color: #1089ff;
--pss-msg-text-color: #7f8596;
--pss-input-bg: #191a1f;
--pss-input-text-color: #d9d9e0;
--pss-input-placeholder-color: #7f8596;
--pss-button-close-bg: #393A47;
--pss-button-close-color: #fff;
--pss-results-title-color: #d9d9e0;
--pss-results-title-color-hover: #fff;
--pss-results-excerpt-color: #8c8ea3;
--pss-results-excerpt-color-hover: #fff;
--pss-results-icon-color: #7f8596;
--pss-results-icon-color-hover: #fff;
--pss-results-highlight-bg: #1089ff;
--pss-highlight-bg: rgba(255,193,7,0.35);
}
}