In this article, I will show you how to implement search in Hugo by using Lunr.js, a lightweight JavaScript search engine.
In this article, I will show you how to implement search in Hugo by using Lunr.js, a lightweight JavaScript search engine. Adding search functionality to your Hugo website enhances user experience and makes it easier for visitors to find relevant content. We will explore the steps involved in integrating Lunr.js, creating a search index from your Hugo content, and incorporating the search feature into your website.
Refer link
Every step I was following this useful article.
https://victoria.dev/blog/add-search-to-hugo-static-sites-with-lunr/
But I also did some changes, like real-time search without refreshing the page.
Import lunr.js
Firstly, import lunr.js or you can run npm install
it. Here I chose import lunr.js cdn.
1
|
<script src="https://unpkg.com/lunr/lunr.js"></script>
|
To conveniently position your search form on any desired location within your website, generate the form as a partial template. Save this template as search-form.html within the layouts/partials/
directory.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
<style>
.input-container {
width: 220px;
position: relative;
}
.icon {
position: absolute;
right: 10px;
top: calc(50% + 5px);
transform: translateY(calc(-50% - 5px));
}
.input {
width: 100%;
height: 40px;
padding: 10px;
transition: .2s linear;
border: 2.5px solid black;
font-size: 14px;
letter-spacing: 2px;
}
.input:focus {
outline: none;
border: 0.5px solid black;
box-shadow: -5px -5px 0px black;
}
.input-container:hover > .icon {
animation: anim 1s linear infinite;
}
@keyframes anim {
0%,
100% {
transform: translateY(calc(-50% - 5px)) scale(1);
}
50% {
transform: translateY(calc(-50% - 5px)) scale(1.1);
}
}
</style>
<div class=" hidden sm:flex input-container ml-12">
<input type="text" name="text" id="search-input" class="input" placeholder="search anything...">
<button type="submit">
<span class="icon">
<svg width="19px" height="19px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path opacity="1" d="M14 5H20" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path> <path opacity="1" d="M14 8H17" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path> <path d="M21 11.5C21 16.75 16.75 21 11.5 21C6.25 21 2 16.75 2 11.5C2 6.25 6.25 2 11.5 2" stroke="#000" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"></path> <path opacity="1" d="M22 22L20 20" stroke="#000" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"></path> </g></svg>
</span>
</button>
</div>
|
Create a search index
Create the search folder in layouts/partials/
path, and create a page named list.html
.
Include the search form in list.htm, also you can use in any other templates.
1
|
{{ partial "search-form.html" . }}
|
For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<!-- In layouts/partials/search/list.html -->
{{ define "main" }}
<section class="s:mt-10 mt-20">
<div class="container sm:my-14" >
<div class="mt-20">
{{ partial "search-form.html" . }}
</div>
<div id="results">
Enter a keyword above to search this site.
</div>
</div>
</section>
{{ end }}
|
Create a search page
Navigate to content folder, create a folder name search, and a file _index.md
Build your search index
In layouts/partials/
folder, create another html file search-index.html
Import lunr.js
cdn and search.js
, I haven’t created search.js
so far.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
{{ define "main" }}
<script src="https://unpkg.com/lunr/lunr.js"></script>
<script src="/js/search.js"></script>
<script>
window.store = {
{{ range .Site.Pages}}
"{{ .Permalink }}": {
"title": "{{ .Title }}",
"tags": [{{ range .Params.Tags }}"{{ . }}",{{ end }}],
"content": {{ .Content | plainify }},
"url": "{{ .Permalink }}"
},
{{ end }}
}
</script>
|
Implement search.js
Compare to this https://victoria.dev/blog/add-search-to-hugo-static-sites-with-lunr/#build-your-search-index article, I did a minor change, no need to refersh the page and get results directly.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
function displayResults (results, store) {
const searchResults = document.getElementById('results')
if (results.length) {
let resultList = ''
// Iterate and build result list elements
for (const n in results) {
const item = store[results[n].ref]
resultList += '<li><p><a href="' + item.url + '">' + item.title + '</a></p>'
resultList += '<p>' + item.content.substring(0, 150) + '...</p></li>'
}
searchResults.innerHTML = resultList
} else {
searchResults.innerHTML = 'No results found.'
}
}
document.addEventListener('DOMContentLoaded', function () {
var searchInput = document.getElementById('search-input');
if (searchInput) {
searchInput.addEventListener('input', function () {
var query = searchInput.value.toLowerCase();
// real-time print out
console.info("query ",query)
if (query) {
document.getElementById('search-input').setAttribute('value', query)
const idx = lunr(function () {
this.ref('id')
this.field('title', {
boost: 15
})
this.field('tags')
this.field('content', {
boost: 10
})
for (const key in window.store) {
this.add({
id: key,
title: window.store[key].title,
tags: window.store[key].category,
content: window.store[key].content
})
}
})
const results = idx.search(query)
// Update the list with results
displayResults(results, window.store)
}else{
const searchResults = document.getElementById('results')
searchResults.innerHTML = 'Enter a keyword above to search this site.'
}
});
}
})
|
Here is the result.