Search
OINK’s search is local search: Hugo generates one JSON index per language at build time, the reader’s browser downloads it, and the search runs in the browser. No crawler, no account, no CDN, and no network access. The theme leaves it off, and one line of configuration turns it on.
The entry point to search is the command palette; how to open it and what else it holds are in Command palette.
Turning on local search
This one key decides whether the index, the Lunr runtime and the search dialog reach a page. Three conditions must hold together:
params.offline_searchis true;- The page is the home page, or uses a shell layout (
docs/book/blog/swagger— see Layouts and page types), or is a landing page withparams.ui.landing_searchon; - The current output is not print.
If any one fails, the build puts no dialog, no index reference and no Lunr into that page. Those resources are not hidden; they are never generated.
Under hugo server the index is generated as well by default, so the
preview behaves like production. On a very large site, where rebuilding the
whole index on every change slows the preview noticeably, turn it off:
Controlling index size
offline_search_index decides how much of each page goes into the index, and so
decides two things at once: whether a reader can find words from the body, and
how large the first search’s download is.
| Value | What is indexed | When to use it |
|---|---|---|
title |
Title, tags, categories, search_keywords |
A very large site where titles alone locate a page |
heading |
The above plus every heading in the page | When headings are specific enough |
summary |
The above plus description and summary | Sites in the thousands of pages; this site uses it |
content |
The above plus the full plain text | The default, suitable up to a few hundred pages |
Any other value fails the build with invalid params.offline_search_index.
offline_search_summary_length is where a result row’s excerpt is cut (default
70), and offline_search_max_results caps the number of results (default 10).
The full definitions are in Configuration.
The reader downloads the whole index before searching for a first word. Past
that size, step offline_search_index down from content to summary.
Adjusting ranking
A page influences its own ranking from front matter:
search_keywords adds matching terms and takes either a string or an array. It
is the more useful of the two: a reader searching pg or GUC reaches a page
whose title only says “PostgreSQL parameters”. In ranking, keywords weigh less
than the title and more than the body.
search_boost is a positive multiplier on the final score, defaulting to 1.0
and applied on top of the text match score. 1.5 does not pin a page to first
place; it moves the page up among results it already matched. Zero, a negative
number and a non-number all warn and are treated as 1.0.
Set a section-wide default once with a cascade:
A page’s own value overrides the inherited one. Pages under this site’s docs/
use search_keywords in exactly this way: each lists the Chinese phrasing, the
English term and the configuration key name.
Keeping a page out of the index
search_exclude is the only spelling; exclude_search and excludeSearch fail
the build with the new name. A page with an empty body is not indexed.
Do not put content that should stay private on the site, and do not use
search_exclude to protect it.
Chinese and CJK
Lunr cannot reliably tokenize Chinese. When the palette detects a CJK character
in the query, the whole query switches to substring matching: it compares title,
keywords, in-page headings, description and body in turn, scores whichever layer
matched, and finally multiplies by search_boost as usual. Both paths rank by
the same rules.
Three things follow:
- A CJK query is a substring match. Searching 主从复制 finds only where those four characters appear consecutively; 复制主从 returns nothing.
search_keywordstherefore pays off most on a Chinese site: write in the synonyms, English terms and abbreviations a reader might use.- While an input method is composing, the palette does not recompute; it searches once the text is committed, so typing Chinese does not refresh results character by character.
When a Chinese query finds nothing, first confirm the Chinese page reached the Chinese index (see Verify below) before suspecting tokenization.
Optional: hosted search
Besides local search, the theme keeps two hosted integrations, both off by
default. Enable only one at a time: with more than one configured the build
warns You have more than one site-search option configured.
Enabling hosted search means accepting that service’s crawling behaviour, availability and privacy boundary, all of which belong in the site’s privacy statement.
Algolia DocSearch
All three values must be written explicitly, and a missing one stops the build: OINK never falls back to another project’s public index. The DocSearch JS and CSS ship with the theme rather than loading from a CDN, but every query is a request to Algolia. Real credentials and a real index are needed for it to work, so nothing is rendered here.
Google Programmable Search
A landing page for the results is needed too:
The search box submits the query to <baseURL>/search/?q=…, and Google’s script
renders the results on that page, which needs access to cse.google.com. It is
likewise an external service and is not rendered here.
Verify
-
Build, and confirm one index per language was generated:
In a development build the filename is
offline-search-index.zh.json; a production build fingerprints it, as inoffline-search-index.zh.7ab….json. One file per language, and a missing one means that language’s pages never reached an index. -
Look inside the index — the first step in diagnosing “Chinese finds nothing”:
The entry count should be close to the number of Chinese pages, and the
keywordsandboostfields should show what the front matter set. -
Open the site, press /, and search once with an English word and once with a Chinese one. Results are grouped by content root, each group named after the first breadcrumb segment.
-
On a subpath deployment (the site under something like
https://example.com/docs/), open the browser’s network panel and confirm the index request carries the subpath. An index request hitting the domain root and returning 404, while the rest of the page works, is the most common cause of “search returns nothing”.
Related
- Command palette — search’s entry point, and the commands and page actions beside it
- Keyboard navigation — the four single keys that open search and commands
- Languages — per-language indexes and untranslated fallback
- Configuration — full definitions of the
offline_search*keys - Page parameters —
search_keywords/search_boost/search_exclude