How to add search functionality to a static web site
Hugo a static web site generator and lunr.js
Since version 0.20 Hugo has a build in capability to create a (customized) index file of available markdown documents down below the content directory tree.
Once this index file is available, we can use lunr.js - a jquery based javascript - to implement a search functionality. The search result pops up instantly, while the user is typing… - pretty neat!
What follows is a brief description to get the whole thing up and running.
Configuration setting (config.toml)
Make sure, to have the most recent hugo version installed, at least V0.20 is required. You might want to run:
hugo version
just to be sure.Add the following to your config.toml configuration file:
[outputs] home = [ "HTML", "RSS", "JSON"]
Note: Make sure to locate the required index.json file in the
layouts
folder. Once the file exists, hugo is going to dump the index to file.The index.json file looks like:
[{{ range $index, $page := .Site.RegularPages }} {{- if ne $page.Type "json" -}} {{- if and $index (gt $index 0) -}},{{- end }} { "__comments": "// hugo interface has changed since hugo v0.59: old: .Site.Pages new: .Site.RegularPages", "uri": "{{ $page.Permalink }}", "title": "{{ htmlEscape $page.Title}}", "tags": [{{ range $tindex, $tag := $page.Params.tags }}{{ if $tindex }}, {{ end }}"{{ $tag| htmlEscape }}"{{ end }}], "description": "{{ htmlEscape .Description}}", "content": {{$page.Plain | jsonify}} } {{- end -}} {{- end -}}]
Once this is done, hugo generates a lunrjs index.json at the root of your public folder.
If you encounter some problems run: hugo --verbose
and check messages and warnings.
Web site configuration:
../layouts/partials/header.html
Typically, that’s where the css files are:
<head> ... {{ if not .Site.Params.disableSearch }} <link href="{{ .Site.BaseURL }}css/auto-complete.css" rel="stylesheet"> {{ end }} ... </head>
../layouts/partials/scripts.html
Please note: as lunr.js is based on jquery, make sure jquery.js gets loaded 1st.
<body> ... <!-- custom search --> {{ if not .Site.Params.disableSearch }} <script type="text/javascript" src="{{ .Site.BaseURL }}js/lunr.min.js"></script> <script type="text/javascript" src="{{ .Site.BaseURL }}js/auto-complete.js"></script> <script type="text/javascript"> var baseurl = "{{ .Site.BaseURL }}"; </script> <script type="text/javascript" src="{{ .Site.BaseURL }}js/search.js"></script> {{ end }} ... </body>
and finally, add a search entry box somewhere in your webpage layout:
{{ if not .Site.Params.disableSearch }} <li class="dropdown"> <a> <i class="fa fa-search"></i> <div class="searchbox pull-right"> <input data-search-input id="search-by" type="text"> </div> </a> </li> {{ end }}
That’s it.