Adding search to a static website
Some websites, like this one, are hard to navigate if there is no way to search the site. Search also requires (at least) client-side code to display the search results. What are the options for a static website?
There are three (almost) free options that I know of:
- Use an external search engine.
- Use client-side search.
- Use server-side search via an API.
Spoiler: my projects currently use the second option.
Use an external search engine.
In some of my older projects the static website was published via Github Pages / Gitlab Pages that had hardly any possibility to add functionality to the website. The solution was to delegate the search to Google, combining the search term that was entered with site:project_website_url. That worked reasonably well, as Google indexes the pages from those big sites often enough. But even then it took quite some time to get new content exposed via the search engine. For small-scale personal sites that is even more problematic: Google is not very interested in these isolated corners of the internet that do not change very often.
Use client-side search.
If server side search is not an option, client side search is the way to go. I've searched for a good option in 2017 and in 2025. I've looked around and four packages. In 2017 I found an early version of Lunr, in 2025 MiniSearch, FlexSearch, Fuse were also available.
After some experimentation, MiniSearch was easiest to use and seem to produce decent results. I was not impressed by the search term suggestions, so I don't use them.
Use server-side search via an API.
Client-side search is very fast, but it required the download of the full search index. If that is a problem, the Azure Static Web App has to option to add an API implementation to the website. That is free to run for low-traffic websites. This may be an option I'll explore in the future. As long as the search index is not too big, the client-side option is guaranteed to be free (for me).
It may well be that the MiniSearch engine can also be used as server-side search engine. If the search index can be make part of the API source, then the actual search can probably be run on Node.js (have read about it, haven't tried it) server backend. The client-side application then fetches the results from the API.
MiniSearch implementation
The custom tool that does the markdown to HTML conversion builds a collection of (markdown) texts, each with a unique id, and creates the MiniSearch search index:
let miniSearch = new MiniSearch({ fields: ['markdown_text'] storeFields: [] }) // Index all documents miniSearch.addAll(documents) JSON.stringify(miniSearch.toJSON());
The javascript is run from .NET with Microsoft.ClearScript.V8, the result is stored in a .json file as part of the static website. Another JSON file is created that relates the ID of the markdown files with the HTML to display for the markdown in the search results. The search page of this website is a modified version of the MiniSearch demo application that fetches both json files:
fetch('/Assets/search_results.json') .then(response => response.json()) .then((allPages) => { resultById = allPages.reduce((byId, page) => { byId[page.id] = page.SearchResultHtml return byId }, {}) fetch('/Assets/search_index.json') .then(response => response.text()) .then((searchIndex) => { return miniSearch = MiniSearch.loadJSON(searchIndex, { fields: ['markdown_text'] }); }) })
The resultById is then used to translate the search results:
let html = '' let results = miniSearch.search(query, searchOptions).map(({ id }) => resultById[id]) results.forEach((result, index) => { html += result + '\n' })
