Single Page Mode

Guide to install the search module in single page mode.

Please make sure you have meet the requirements.

Examples

There is an example site and it’s source code to help you get started.

There also a guide for integrating Docsy with the search module.

Import the module

hugo.yaml

1module:
2  imports:
3  - path: github.com/hugomods/search

hugo.toml

1[module]
2  [[module.imports]]
3    path = 'github.com/hugomods/search'

hugo.json

1{
2   "module": {
3      "imports": [
4         {
5            "path": "github.com/hugomods/search"
6         }
7      ]
8   }
9}

Base Template

You should specify the lang and dir attributes on <html> tag of base template (layouts/_default/baseof.html by default), so that the module can recognize and render in current page language.

1<html
2  lang="{{ .Lang }}"
3  {{ with .Language.LanguageDirection }}dir="{{ . }}"{{ end }}>
4  <!-- ... -->
5</html>

The best practice is to include the search’s CSS and JS on the search page only when sharing the same base template.

1<html
2  lang="{{ .Lang }}"
3  {{ with .Language.LanguageDirection }}dir="{{ . }}"{{ end }}>
4  {{ if $isSearchPage }}
5    <!-- Search CSS -->
6    <!-- Search JS -->
7  {{ end }}
8</html>

But we couldn’t do that, since there isn’t a way to recognize whether the current page is a search page. See hugomods/search#76 and gohugoio/hugo#9368.

So we need a workaround, according to the Hugo look up order, we can achieve this by creating the baseof.search.html template for single search page, see the demo site’s baseof.search.html.

Include the CSS

There are multiple approaches to include the CSS.

Include the CSS via Hugo Pipes

Recommended when you’re using Hugo pipes to build CSS from source, it combines your styles and search styles into one bundle file, which is helpful to reduce the HTTP requests.

 1{{/* NOTE: we must change the CSS target to separate the style between LTR and RTL sites. */}}
 2{{/* Otherwise, Hugo may treats it as the same style (cached). */}}
 3{{/* Ignore it if your themes and sites aren't going to support RTL. */}}
 4{{ $rtl := eq .Language.LanguageDirection "rtl" }}
 5{{ $cssTarget := cond $rtl "css/main.rtl.css" "css/main.css" }}
 6{{ $css := resources.Get "main.scss" | toCSS }}
 7{{/* If you have a prebuilt CSS, replace the $css with the following. */}}
 8{{ $css := resources.Get "main.css" }}
 9{{ $searchCSS := partial "search/assets/css-resource" . }}
10{{ $css = slice $searchCSS $css | resources.Concat $cssTarget }}
11<link rel="stylesheet" href="{{ $css.RelPermalink }}" />
  • The main.scss/main.css is your styles file, which located in the assets folder, replace it with yours.
  • Note that slice $searchCSS $css puts the $css after $searchCSS, so that $css style can override the search’s.
  • The search/assets/css-resource is a partial that returns a search CSS resource.

Import the CSS via SCSS File

1@import "search/scss/index";

This way is more complex than the former, you’ll need to take care of the PostCSS, Autoprefixer and RTLCSS. See how CSS resource partial does.

Include the CSS via Partial

This approach generates a <link> tag.

1{{ partial "search/assets/css" . }}

Include the JavaScript

We can achieve this via two ways.

Include the JavaScript via Hugo Pipes

Recommended when you’re using Hugo pipes to build JS from source, it combines your JS and search JS into one bundle file, which is helpful to reduce the HTTP requests.

1{{ $js := resources.Get "main.ts" | js.Build }}
2{{/* If you have a prebuilt JS file, use the following instead. */}}
3{{ $js := resources.Get "main.js" }}
4{{ $searchJS := partial "search/assets/js-resource" . }}
5{{ $js = slice $js $searchJS | resources.Concat "js/main.js" }}
6<script src="{{ $js.RelPermalink }}" defer></script>

Please note that you should not set the async attribute on the script.

  • The main.ts/main.js is your JavaScript file, which located in the assets folder, replace it with yours.
  • The search/assets/js-resource is a partial that returns a search JS resource.

Include the JavaScript via Partial

This partial will generate a <script> tag.

1{{ partial "search/assets/js" . }}

Create Entrances

We’ll need to create a entrance for users, such as a link/menu to the search page, or a search form.

Create Entrances via Partial

1{{ $searchURL := partial "search/functions/search-url" . }}
2
3{{/* Link to search page. */}}
4<a href="{{ $searchURL }}">Search</a>
5
6{{/* Search form. */}}
7<form action="{{ $searchURL }}">
8  <input type="search" name="q">
9</form>

The single search page accepts the following parameters from URL.

  • q: query, the search input value.

Create Entrances via Menu

When you’re not familiar with the partials, you can simply add a menu with the /search URL (related to the baseURL).

Set Up the Search Page and Indices

Append the Search and SearchIndex formats into outputs.home.

hugo.yaml

1outputs:
2  home:
3  - HTML
4  - RSS
5  - Search
6  - SearchIndex

hugo.toml

1[outputs]
2  home = ['HTML', 'RSS', 'Search', 'SearchIndex']

hugo.json

 1{
 2   "outputs": {
 3      "home": [
 4         "HTML",
 5         "RSS",
 6         "Search",
 7         "SearchIndex"
 8      ]
 9   }
10}