The search module generates a full-text search database from your site content and injects the necessary runtime assets into your bundle for client-side search. Queries run entirely in the browser — no server required.
Search is disabled by default. Enable it in your config.scriban:
with search
enable = true
end
All
search.*properties shown on this page are set inside your site'sconfig.scriban, within awith search/endblock.
During the build, Lunet:
/js/lunet-search.sqlite).At runtime, the search database is loaded in the browser and queries run client-side with BM25 ranking. Results include URL, title, and a highlighted content snippet.
No search UI is injected. The plugin provides only the search engine and database. Your theme or layout must implement the search input and results display using the
LunetSearchJavaScript API (see Client-side API below).
with search
enable = true
url = "/js/lunet-search.db" # base URL for the search database
worker = false # use a web worker for search (default: false)
engine = "sqlite" # search engine backend (default: "sqlite")
end
| Property | Type | Default | Description |
|---|---|---|---|
search.enable |
bool | false |
Enable search index generation |
search.url |
string | "/js/lunet-search.db" |
Base output URL for the search database. The actual file written uses a .sqlite extension |
search.worker |
bool | false |
Run search in a web worker to avoid blocking the main thread |
search.engine |
string | "sqlite" |
Search engine backend name. Currently only "sqlite" is built-in |
search.excludes |
list | [] |
Glob patterns for pages to exclude from the search index |
Note on file extension: Even though
urldefaults to.db, the output file is always written with a.sqliteextension (e.g./js/lunet-search.sqlite). The client-side JavaScript also loads from the.sqlitepath by default.
Use glob patterns to exclude pages from the search index. Patterns must be absolute paths:
with search
excludes.add ["/api/**", "/draft/**"]
end
Pages with discard: true in front matter are excluded from all output, including search.
By default, the SQLite engine and search queries run on the main thread. Set worker = true to offload search to a Web Worker:
with search
enable = true
worker = true
end
In worker mode, the search database is loaded asynchronously in a background thread. Queries are sent to the worker via MessageChannel and results are returned through the port. The trade-off is that available reports true immediately (before the worker finishes loading), so early queries may be delayed.
In non-worker mode (default), all assets are inlined into the bundle and the database is loaded on the main thread. The available property accurately reflects whether initialization is complete.
The search engine uses the browser Cache API (caches.open("lunet.cache")) to cache the database locally. On subsequent visits, a HEAD request checks ETag, Last-Modified, and Content-Length headers. The database is only re-downloaded when the server version has changed.
The plugin exposes a global DefaultLunetSearch (or DefaultLunetSearchPromise in non-worker mode) object. After initialization, use the query() method:
const search = await DefaultLunetSearchPromise;
const results = search.query("my search term");
// results: [{ url: "/page/", title: "Page Title", snippet: "...matched <b>text</b>..." }]
Each result contains:
| Property | Type | Description |
|---|---|---|
url |
string | URL of the matching page |
title |
string | Page title |
snippet |
string | Content snippet with <b> highlighted matches |
Results are ranked by BM25 with default weights: URL (3.0), title (2.0), content (1.0). Snippet length defaults to 20 words. These weights are defined in the JavaScript client and are not configurable from Scriban.
FTS5 query syntax: The search input supports FTS5 query syntax including
AND,OR,NOT,*(prefix), andNEAR. Malformed queries may cause errors.
search.enable is false (default), no processing occurs.search.engine does not match any registered engine, an error is logged but the build continues.search.url is not a valid absolute path, an error is logged and search is skipped.