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.
