Skip to content

Search and Tags

Mikhail Deynekin edited this page Nov 13, 2026 · 1 revision

Search and tags

Search is a pure-PHP inverted index in storage/index/search-index.json — no database, no external service. Titles weigh more than headings, headings more than body text; documents matching every word rank above partial matches. The index rebuilds itself when the corpus fingerprint (file count, newest mtime, total size) changes, and an admin can force a rebuild.

Operators

Operator Example Meaning
tag: tag:ops documents whose frontmatter carries that tag
tag:"…" tag:"release notes" quoted form for tags containing spaces (normalised to release-notes)
path: path:runbooks/ case-insensitive prefix match on the relative path

They combine with each other and with free text:

deploy tag:ops path:runbooks/

returns documents that contain "deploy", carry ops and live under runbooks/. A filter on its own is a valid query (it lists matching documents). An unknown word: is treated as prose — a colon never silently drops a word from the query.

Why tags live in the index

The index stores each document's tags, so tag: needs no second lookup and no per-document file read. Adding or removing a tag in frontmatter changes the corpus fingerprint, which rebuilds the index on the next search.

Surfaces

Where What
/index.php?page=search&q=… full-text page, with a reminder of the operators under the box
Ctrl/⌘+K command palette: documents, headings, actions
/index.php?page=tags tag index; each tag lists its documents
?api=search&q=…&limit=50 JSON results with total, took_ms, filters, results[]
?api=suggest&q=… typeahead: titles and headings

?api=search echoes the parsed filters back ("filters":{"tags":["ops"],"path":"runbooks"}), which makes a client able to tell "nothing matched" from "the filter was not understood".

Limits

SEARCH_MAX_RESULTS caps the page size (default 50, hard ceiling 100 in the API); the query itself is capped at 200 characters. Snippets are generated for the top ten results only, so a large corpus stays fast.

Clone this wiki locally