This post is about implementing the search option on static websites like Hugo
How to implement search option on static websites like Hugo Link to heading
I am using static website builder called to publish my blog. I wanted something simple and less resource utilized. Hugo was best option for me. I am using Hugo Coder theme. Pagefind is simple java library which specially designed for static websites.
Add the pagefind as git sub module. My existing hugo theme under themes folder. Under the same themes folder pagefind folder can be added.
git submodule add https://github.com/CloudCannon/pagefind.git themes/pagefind
Update the config.toml
[params]
search_engine = "pagefind"
[outputs]
home = ["HTML", "RSS", "JSON"]
create a json format file called index.json under themes/(themename)/layout/_default
{{- $pages := where .Site.RegularPages "Type" "not in" (slice "json" "css" "js") -}}
{{- printf "{\"version\":\"%s\",\"pages\":[" (now.Format "20060102150405") -}}
{{- range $index, $page := $pages -}}
{{- if $index }},{{ end -}}
{{- printf "{\"title\":%q,\"description\":%q,\"url\":%q,\"content\":%q}" $page.Title $page.Description $page.Permalink $page.Plain -}}
{{- end -}}
{{- printf "]}" -}}
Now add the search bar to site. create new form search-form.html in themes/hugo-coder/partials folder
<form id="search-form">
<input type="search" id="search-input" placeholder="Search" />
<button type="submit">Search</button>
</form>
<div id="search-results"></div>
include the search-form.html partial in your main layout file (e.g., layouts/_default/baseof.html).
{{ partial "search-form.html" . }}
Create a new file called pagefind.js in the static/js( themes/hugo-coder/static/js)
document.getElementById("search-form").addEventListener("submit", function (event) {
event.preventDefault();
const searchInput = document.getElementById("search-input");
const searchResults = document.getElementById("search-results");
fetch("/index.json")
.then((response) => response.json())
.then((data) => {
const searchTerm = searchInput.value.toLowerCase();
const matchingPages = data.pages.filter((page) => {
return (
page.title.toLowerCase().includes(searchTerm) ||
page.description.toLowerCase().includes(searchTerm) ||
page.content.toLowerCase().includes(searchTerm)
);
});
searchResults.innerHTML = "";
if (matchingPages.length > 0) {
matchingPages.forEach((page) => {
const resultItem = document.createElement("div");
const resultTitle = document.createElement("h3");
const resultLink = document.createElement("a");
const resultDescription = document.createElement("p");
resultLink.href = page.url;
resultLink.textContent = page.title;
resultTitle.appendChild(resultLink);
resultDescription.textContent = page.description;
resultItem.appendChild(resultTitle);
resultItem.appendChild(resultDescription);
searchResults.appendChild(resultItem);
});
} else {
searchResults.innerHTML = "<p>No results found.</p>";
}
});
});
Include the pagefind.js script in your main layout file (themes/hugo-coder/layouts/_default/baseof.html). Add this line right before the closing