Views

Enhancing Hugo Project

Enhancing Hugo Project
Page content

In this article we will see some advanced customization done to the basic Hugo project that was created here.

Once we have the basic project created in Hugo and hosted on GitHub Pages, we can look at customizing the project, for the ease of use.

In this article, I will focus on some of the customizations, I have used to make the project look and feel better and also increase the ease of use, as I create more posts.

NOTE:

  1. When we have to update the files that are existing in Themes folder, it is always a good practice to copy that file into the equivalent path of our local root folder, for updating.
  2. Hugo, when it has to fetch a file, it will always first search the local folder and then the Themes folder.
  3. I am using Mainroad theme and hence all the updates shown below are relevant to that theme. If you are using different theme, some of the file path and attributes may vary.

Auto-numbering to Headers and TOC in Pages

When you generate a website using Hugo, it doesn’t provide any out of the box Auto Numbering support for Headings, Sub-Headings and TOC in Hugo Pages.

Follow these steps to enable Auto Numbering feature in your Hugo website:

Add autonumbering property to all our pages

First of all, add a custom property autonumbering to all our Hugo pages.

We can add this to all our pages in 2 ways:

  1. We can also add this to the config.toml file, so that it is available for every pages.
[Params]
  ...
  autonumbering = true
  ...
...
  1. By adding it to the FrontMatter of the every page or by adding to the default.md template.
---
...
autonumbering: true
---

When we add it to the config.toml file, it will be available for every page, by default and then we can enable or disable auto-numbering for a specific page using this property on that page’s FrontMatter.

Add CSS Class to single.html

Next, we are going to edit layouts/_default/single.html file and add a condition on article element to add autonumbering CSS class based on autonumbering property is enabled or disabled.

 1{{ define "main" }}
 2<main>
 3  <article class="post" {{- if .Param "autonumbering" }} autonumbering {{- end }}>
 4    <header>
 5     ...
 6    </header>	
 7     ...
 8    <footer>
 9     ...
10    </footer>
11  </article>
12</main>
13{{ end }}

Add CSS Styles to style.css

At last, add the following CSS Styles snippet in the CSS files located at /assets/style.css folder.

 1/* Start of Auto Numbering */
 2body {counter-reset: h2}
 3h2 {counter-reset: h3}
 4h3 {counter-reset: h4}
 5h4 {counter-reset: h5}
 6
 7article[autonumbering] h2:before {counter-increment: h2; content: counter(h2) ". "}
 8article[autonumbering] h3:before {counter-increment: h3; content: counter(h2) "." counter(h3) ". "}
 9article[autonumbering] h4:before {counter-increment: h4; content: counter(h2) "." counter(h3) "." counter(h4) ". "}
10
11article[autonumbering] .toc__menu ul { counter-reset: item }
12article[autonumbering] .toc__menu li a:before { content: counters(item, ".") ". "; counter-increment: item }
13/* End of Auto Numbering */

with-auto-numbering.jpeg
With Auto Numbering


Adding Menus

When we generate a website using Hugo, we generally show a menu header on website page and other pages.

Sometime we need the support for nested menu structure which is not readily available with Hugo.

Follow these steps to enable menus and sub-menus feature in your Hugo website:

Update config.toml

Let us update config.toml with menu and submenu configuration to generate a nested menu structure.

 1[menu]
 2  [[menu.main]]
 3    identifier = "home"
 4    name = "Home"
 5    url = "/"
 6    weight = 1
 7  [[menu.main]]
 8    identifier = "category"
 9    name = "Category"
10    url = "/category"
11    weight = 2
12    [[menu.main]]
13      identifier = "category1"
14      name = "Category1"
15      url = "/tags/category1"
16      parent = "category"
17      weight = 1
18    [[menu.main]]
19      identifier = "category2"
20      name = "Category2"
21      url = "/tags/category2"
22      parent = "category"
23      weight = 2
24    [[menu.main]]
25      identifier = "category3"
26      name = "Category3"
27      url = "/tags/category3"
28      parent = "category"
29      weight = 3
30  [[menu.main]]
31    identifier = "about"
32    name = "About Us"
33    url = "/about/"
34    weight = 4

Lets us understand the fields in [[menu.main]]:

  • identifier should be unique name of menu within the menu structure.
  • name should be the name which you want to display on the menu item.
  • url is a relative URL which will be opened when you click on the menu item.
  • weight is for sequencing the menu items. Menu items with less weight appear first in the menu.
  • parent is used in submenu item only to tell who is the parent of the submenu. It uses the identifier of the parent.

Create layouts/partials/menu.html

This is the default menu.html we get in the theme folder.

 1{{- if .Site.Menus.main }}
 2<nav class="menu">
 3	<button class="menu__btn" aria-haspopup="true" aria-expanded="false" tabindex="0">
 4		<span class="menu__btn-title" tabindex="-1">{{ T "menu_label" }}</span>
 5	</button>
 6	<ul class="menu__list">
 7		{{- $currentNode := . }}
 8		{{- range .Site.Menus.main }}
 9		{{- if .Name }}
10		<li class="menu__item{{ if or ($currentNode.IsMenuCurrent "main" .) ($currentNode.HasMenuCurrent "main" .) }} menu__item--active{{ end }}">
11			<a class="menu__link" href="{{ .URL }}">
12				{{ .Pre }}
13				<span class="menu__text">{{ .Name }}</span>
14				{{ .Post }}
15			</a>
16		</li>
17		{{- end }}
18		{{- end }}
19		
20	</ul>
21</nav>
22{{ else -}}
23<div class="divider"></div>
24{{- end }}

This does not support sub-menu categorization.

default-menu-without-submenu.jpeg
Default Themes Menu without Sub Menu

Copy the menu.html from /themes/<<UR-THEME>>/layouts/partial/ to /layouts/partial/and update as given below, to include sub-menus

 1{{- if .Site.Menus.main }}
 2<nav class="menu">
 3	<button class="menu__btn" aria-haspopup="true" aria-expanded="false" tabindex="0">
 4		<span class="menu__btn-title" tabindex="-1">{{ T "menu_label" }}</span>
 5	</button>
 6	<ul class="menu__list">
 7		{{- $currentNode := . }}
 8		{{- range .Site.Menus.main }}
 9		{{- if .Name }}
10		{{- if .HasChildren }}
11		<li class="menu__item menu__dropdown{{ if or ($currentNode.IsMenuCurrent "main" .) ($currentNode.HasMenuCurrent "main" .) }} menu__item--active{{ end }}">
12			<a class="menu__link" href="{{ .URL }}">
13				{{ .Pre }}
14				<span class="menu__text">{{ .Name }}</span>
15				<label class="drop-icon" for="{{ .Name }}"></label>
16				{{ .Post }}
17			</a>
18			<input type="checkbox" id="{{ .Name }}">
19			<ul class="submenu__list">
20				{{ range .Children }}
21					<li class="menu__item{{ if or ($currentNode.IsMenuCurrent "main" .) ($currentNode.HasMenuCurrent "main" .) }} menu__item--active{{ end }}">
22					<a class="menu__link" href="{{ .URL }}">
23						{{ .Pre }}
24						<span class="menu__text">{{ .Name }}</span>
25						{{ .Post }}
26					</a>
27					</li>
28				{{ end }}
29			</ul>
30		</li>
31		{{- else }}
32		<li class="menu__item{{ if or ($currentNode.IsMenuCurrent "main" .) ($currentNode.HasMenuCurrent "main" .) }} menu__item--active{{ end }}">
33			<a class="menu__link" href="{{ .URL }}">
34				{{ .Pre }}
35				<span class="menu__text">{{ .Name }}</span>
36				{{ .Post }}
37			</a>
38		</li>{{- end }}
39		{{- end }}
40		{{- end }}
41	</ul>
42</nav>
43{{ else -}}
44<div class="divider"></div>
45{{- end }}

Update assets/css/styles.css

Include the css required for styling the Main Menus and Sub Menus. This is an important step, without which Menus and Submenus will not work the way we want them to.

  1/* Start of Main Menu and Submenu */
  2.no-js .menu__btn {
  3	display: none;
  4  }
  5  
  6  .menu__btn {
  7	display: block;
  8	width: 100%;
  9	padding: 0;
 10	font: inherit;
 11	color: #fff;
 12	background: #2a2a2a;
 13	border: 0;
 14	outline: 0;
 15  }
 16  
 17  .menu__btn-title {
 18	position: relative;
 19	display: block;
 20	padding: 10px 15px;
 21	padding: 0.625rem 0.9375rem;
 22	font-weight: 700;
 23	text-align: right;
 24	text-transform: uppercase;
 25	cursor: pointer;
 26	-webkit-user-select: none;
 27	-moz-user-select: none;
 28	-ms-user-select: none;
 29	-o-user-select: none;
 30	user-select: none;
 31  }
 32  
 33  :focus > .menu__btn-title {
 34	box-shadow: inset 0 0 1px 3px #e22d30;
 35  }
 36  
 37  button:not(:-moz-focusring):focus > .menu__btn-title {
 38	box-shadow: none;
 39  }
 40  
 41  .menu__btn:focus,
 42  .menu__btn-title:focus {
 43	outline: 0;
 44  }
 45  
 46  .js .menu__btn--active {
 47	color: #e22d30;
 48  }
 49  
 50  .menu__list,
 51  .submenu__list {
 52	list-style: none;
 53	background: #2a2a2a;
 54  }
 55  
 56  .menu__item:hover > a {
 57	background: #e22d30;
 58  }
 59  
 60  .menu__item:first-child {
 61	border: 0;
 62  }
 63  
 64  .menu__item--active {
 65	background: #e22d30;
 66  }
 67  
 68  .menu__link {
 69	display: block;
 70	padding: 10px 15px;
 71	padding: 0.625rem 0.9375rem;
 72	font-weight: 700;
 73	color: #fff;
 74	text-transform: uppercase;
 75  }
 76  
 77  .menu__list .menu__item .submenu__list {
 78	background: #2a2a2a;
 79	visibility: hidden;
 80	opacity: 0;
 81	position: absolute;
 82	max-width: 15rem;
 83	transition: all 0.5s ease;
 84	border-top: 5px solid #e22d30;
 85	display: none;
 86  }
 87  
 88  .menu__item.menu__dropdown input[type="checkbox"] {
 89	display: none;
 90  }
 91  
 92  .menu__list .menu__item:hover > .submenu__list,
 93  .menu__list .menu__item:focus-within > .submenu__list,
 94  .menu__list .menu__item .submenu__list:hover,
 95  .menu__list .menu__item .submenu__list:focus {
 96	visibility: visible;
 97	opacity: 1;
 98	display: block;
 99  }
100  
101  .menu__link:hover {
102	color: #fff;
103  }
104  
105  .js .menu__list {
106	position: absolute;
107	z-index: 1;
108	width: 100%;
109	visibility: hidden;
110	-webkit-transform: scaleY(0);
111	transform: scaleY(0);
112	-webkit-transform-origin: top left;
113	transform-origin: top left;
114  }
115  
116  .js .menu__list--active {
117	visibility: visible;
118	border-top: 1px solid rgba(255, 255, 255, 0.1);
119	border-bottom: 1px solid rgba(255, 255, 255, 0.1);
120	-webkit-transform: scaleY(1);
121	transform: scaleY(1);
122  }
123  
124  .menu__list--transition {
125	transition: visibility 0.15s ease, transform 0.15s ease,
126	  -webkit-transform 0.15s ease;
127  }
128  
129  @media screen and (min-width: 767px) {
130	.menu {
131	  border-bottom: 5px solid #e22d30;
132	}
133  
134	.menu__btn {
135	  display: none;
136	}
137  
138	.menu__list,
139	.js .menu__list {
140	  position: relative;
141	  display: -webkit-flex;
142	  display: flex;
143	  -webkit-flex-wrap: wrap;
144	  flex-wrap: wrap;
145	  visibility: visible;
146	  border: 0;
147	  -webkit-transform: none;
148	  transform: none;
149	}
150  
151	.menu__item {
152	  border-left: 1px solid rgba(255, 255, 255, 0.1);
153	}
154  }
155  
156  @media screen and (max-width: 767px) {
157	.menu__item.menu__dropdown .drop-icon {
158	  position: absolute;
159	  right: 1rem;
160	  top: auto;
161	}
162  
163	.menu__item.menu__dropdown input[type="checkbox"] + .submenu__list {
164	  display: none;
165	}
166  
167	.menu__item.menu__dropdown input[type="checkbox"]:checked + .submenu__list {
168	  border: none;
169	  padding-left: 20px;
170	  visibility: visible;
171	  opacity: 1;
172	  display: block;
173	  position: relative;
174	  max-width: 100%;
175	}
176  }
177  
178  @media screen and (max-width: 620px) {
179	.menu__item.menu__dropdown .drop-icon {
180	  position: absolute;
181	  right: 1rem;
182	  top: auto;
183	}
184  
185	.menu__item.menu__dropdown input[type="checkbox"] + .submenu__list {
186	  display: none;
187	}
188  
189	.menu__item.menu__dropdown input[type="checkbox"]:checked + .submenu__list {
190	  border: none;
191	  padding-left: 20px;
192	  visibility: visible;
193	  opacity: 1;
194	  display: block;
195	  position: relative;
196	  max-width: 100%;
197	}
198  }
199/* End of Main Menu and Submenu */

Now you can see sub-menu categories also appear.

menu-with-submenu.jpeg
Menu with Sub Menu


Total Number of Posts on Each Menu Category page

It would be good to display the total number of posts per page. Most of the Hugo Themes, do not have them out of the box.

Total Posts Count to Homepage

In order to display the total number of posts on the Homepage, we need to make following config changes.

  • Update the layouts/index.html
 1{{ define "main" }}
 2<main class="main list" role="main">
 3	<!-- Get total number of posts -->
 4	<header class="homepage-header">
 5        <h2>All Posts ({{ len (where .Site.RegularPages "Section" "!=" "") }})</h2> 
 6    </header>
 7	{{- with .Content }}
 8	...
 9	{{ end }}
10</main>
11{{ partial "pagination.html" . }}
12{{ end }}

total-posts-count-homepage.jpeg
Total Posts count on Homepage

Total Posts Count on each Category Page

In order to get the Total Post count on each Category Page, we make the following config changes.

  • Update the layouts/_default/list.html
 1{{ define "main" }}
 2<main class="main list" role="main">
 3	{{- with .Title }} 
 4	<!-- Get number of posts per each category page -->
 5	<header class="main__header">
 6		<h1 class="main__title"> 
 7			All Posts About {{ . }}
 8			{{ $title := urlize . }}
 9			{{ with $.Site.Taxonomies.categories }}
10				{{ range $name, $taxonomy := . }}
11					{{ $term := urlize $name }}
12					{{ if eq $term $title }}
13						({{ $taxonomy.Count }})
14					{{ end }}
15				{{ end }}
16			{{ end }}
17		</h1>
18	</header>
19	{{- end }}
20	{{- with .Content }}
21	...
22	{{- end }}
23</main>
24{{ partial "pagination.html" . }}
25{{ end }}

total-posts-count-category-page.jpeg
Total Posts count per Category Page


Add Back to Top

When we are in the middle or at the bottom of a post and we need to move to the top, that is not readily available in Hugo.

Follow these steps to enable Back to Top feature in your Hugo website:

Create layouts/partials/back-to-top.html

1<script src="https://unpkg.com/vanilla-back-to-top@7.2.1/dist/vanilla-back-to-top.min.js"></script>
2<script>addBackToTop({
3  diameter: 56,
4  backgroundColor: 'rgb(255, 82, 82)',
5  textColor: '#fff'
6})</script>

Call this file in every post

Once the above is created, we need to call this file as first line of code in every post.

1{{ partial "back-to-top.html" . }}

This can be added to the default.md template in order to make sure it is enabled for all new posts, by default.

This would add the arrow for moving to the top.

back-to-top-button.jpeg
Back to Top Button


Adding Line Numbers and Highlights to the Code Sample

It would be good to display line numbers and highlight few lines in the code samples in the post.

For more details on the Highlight Shortcode, refer this.

  • linenos: configure line numbers. Valid values are true, false, table, or inline.
  • hl_lines: lists a set of line numbers or line number ranges to be highlighted.
  • linenostart=199: starts the line number count from 199.
{{< highlight go "linenos=true,hl_lines=2,linenostart=199" >}}
// ... code
{{< / highlight >}}

This would result in following section

199
200
201
202
203
204
<script src="https://unpkg.com/vanilla-back-to-top@7.2.1/dist/vanilla-back-to-top.min.js"></script>
<script>addBackToTop({
  diameter: 56,
  backgroundColor: 'rgb(255, 82, 82)',
  textColor: '#fff'
})</script>
{{< highlight go "linenos=table,hl_lines=2,linenostart=199" >}}
// ... code
{{< / highlight >}}

This would result in following section

199
200
201
202
203
204
<script src="https://unpkg.com/vanilla-back-to-top@7.2.1/dist/vanilla-back-to-top.min.js"></script>
<script>addBackToTop({
  diameter: 56,
  backgroundColor: 'rgb(255, 82, 82)',
  textColor: '#fff'
})</script>
{{< highlight go "linenos=inline,hl_lines=2,linenostart=199" >}}
// ... code
{{< / highlight >}}

This would result in following section

199<script src="https://unpkg.com/vanilla-back-to-top@7.2.1/dist/vanilla-back-to-top.min.js"></script>
200<script>addBackToTop({
201  diameter: 56,
202  backgroundColor: 'rgb(255, 82, 82)',
203  textColor: '#fff'
204})</script>

Reading Time

It will be good if readers can get to know, how much time does the particular post take to read, on an average. Hugo provides this functionality, we need to configure our code to enable that.

Follow these steps to enable Reading Time feature in your Hugo website:

Create layouts/partials/post_meta/reading-time.html

1<div class="meta__item meta__icon">
2    {{- partial "svg/reading-time.svg" -}} {{ if gt .ReadingTime 1 }} {{ .ReadingTime }} Minutes  {{ else }} Less Than a Minute {{ end }} Read   
3</div>

Download svg image reading-time.svg to the layouts/partials/svg folder

<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg width="18" height="18" viewBox="0 0 88.965 88.966">
	<polygon points="66.436,56.656 61.639,56.656 61.639,72.438 75.096,72.438 75.096,67.641 66.436,67.641"/>
	<path d="M65.049,46.49v-3.342V23.541c0,0,0.008-6.385,0-6.465l-3.746-7.59l3.324-6.32c0.354-0.67,0.33-1.475-0.062-2.121
		C64.174,0.397,63.471,0,62.715,0H5.301C4.11,0,3.143,0.967,3.143,2.16l0.052,80.307h10.369V16.841H7.461V4.32h51.68l-2.186,4.15
		c-0.328,0.625-0.332,1.369-0.007,1.998l3.295,6.373h-42.43v65.625h7.915h6.818h14.526h2.236c3.865,4,9.273,6.5,15.264,6.5
		c11.719,0,21.25-9.532,21.25-21.25C85.825,56.158,76.547,46.746,65.049,46.49z M64.575,81.966c-7.857,0-14.25-6.394-14.25-14.25
		s6.393-14.25,14.25-14.25s14.25,6.394,14.25,14.25S72.432,81.966,64.575,81.966z"/>	
</svg>

Update the config.toml

Update the post_meta section in config.toml to include reading-time

post_meta = ["date", "categories", "reading-time"]

These above changes would result in following

reading-time.jpeg
Reading Time


Render image with alt text, caption and center align

We can configure Hugo to render images with Center align, having alt text and customized style for caption.

Create layouts/_default/_markup/render-image.html

1{{ if .Title }}
2  <figure>
3    <img src="{{ .Destination | safeURL }}" alt="{{ .Text }}" style="display: block;margin: 0.7rem auto;">
4    <figcaption style="text-align: center;font-style: italic;font-size: smaller;">{{ .Title }}</figcaption>
5  </figure>
6{{ else }}
7  <img src="{{ .Destination | safeURL }}" alt="{{ .Text }}">
8{{ end }}

Every time a link is clicked in the post, make sure they always open in the new tab

Create layouts/_default/_markup/render-link.html

1<a href="{{ .Destination | safeURL }}"{{ with .Title}} title="{{ . }}"{{ end }}
2{{ if or (strings.HasPrefix .Destination `http`) (strings.HasPrefix .Destination `/`) }} target="_blank"{{ end }}>{{ .Text }}</a>

Display the current year automatically in the footer.

Update layouts/partials/footer.html

1<footer class="footer">
2	<div class="container footer__container flex">
3		{{ partial "footer_links.html" . }}
4		<div class="footer__copyright">
5			&copy; 2020-{{ now.Format "2020" }} {{ .Site.Params.copyright | default .Site.Title }}
6		</div>
7	</div>
8</footer>

footer-with-year.jpeg
Footer with auto updated current year


Visitors Count

Keep track of number of visitors to a single post.

Create layouts/partials/visitor-count.html

1<div class="views">
2    <span class="views">
3        <img src="https://visitor-badge.glitch.me/badge?page_id={{ .Permalink }}" alt="Views"/>
4    </span>
5</div>

Update layouts/_default/single.html

Include the visitor-count.html on top of the single.html

 1{{ define "main" }}
 2<main>
 3  <article class="post" {{- if .Param "autonumbering" }} autonumbering {{- end }}>
 4    <header class="post__header">{{ partial "visitor-count.html" . }}
 5     ...
 6    </header>	
 7     ...
 8    <footer>
 9     ...
10    </footer>
11  </article>
12</main>
13{{ end }}

visitor-count.jpeg
Visitor Count


Google Analytics

Add some Analytics to your site with the help of Google Analytics.

Create Account in Google Analytics

First you need to create an Account in Google Analytics here, if you don’t have already.

Configure Google Analytics

  1. Click on Admin in the bottom left-hand corner of your dashboard.

  2. In Admin, in the Account column, click Create Account.

  3. Provide an account name. Configure the data-sharing settings to control which data you share with Google.

  4. Click Next to add the first property to the account.

  5. In the Property column, click Create Property.

    google-analytics-account-property.jpeg
    Google Analytics- Account & Property

  6. Enter a name for the property and select the reporting time zone and currency.

    • If a visitor comes to your website on a Tuesday in their time zone, but it’s Monday in your time zone, the visit is recorded as having occurred on Monday.
  7. Click Next. Select your industry category and business size.

  8. Click Create and accept the Analytics Terms of Service and the Data Processing Amendment.

  9. In the Property column, click Data Streams then Add stream.

  10. Click iOS app, Android app, or Web (Since we are doing for our website, we will choose Web.)

  11. Enter the URL of your primary website, e.g., “example.com”, and a Stream name, e.g. “Example, Inc. (web stream)”.

  12. You have the option to enable or disable Enhanced measurement.

  13. Click Create stream.

Add G- ID to Hugo Website

  1. You’ll need to add the Analytics tag to your web pages to begin seeing data in your new Google Analytics 4 property.

  2. Click Admin, in the Property column, check that you have your new Google Analytics 4 property selected, then click Data Streams, then Web. Click the data stream.

  3. Your “G-” ID appears at upper right. Copy the “G-” ID.

    google-analytics-g-id.jpeg
    Google Analytics- G- ID

  4. Go to the config.toml and paste the “G-” ID obtained above, for the parameter googleAnalytics.

googleAnalytics="G-C3MLHYNGL3"
  1. Deploy the code and that’s it.

From now on, our website will be tracked on the Google Analytics, providing us all information regarding pages views, posts accessed, number of users and many more.

Track localhost

This code would not track the hits to the localhost. If you want localhost also to be tracked, then you need to modify the code.

In the layouts/_default/baseOf.html file

1{{- if not .Site.IsServer }}
2	{{- if hasPrefix .Site.GoogleAnalytics "G-" }}
3	{{ template "_internal/google_analytics.html" . }}
4	{{- else }}
5	{{ template "_internal/google_analytics_async.html" . }}
6	{{- end }}
7{{- end }}

Remove the highlighted lines from the section above, so that Google Analytics can track the localhost also.


Add Comments to your Hugo Website

Utteranc.es is a lightweight comments widget, which allows you to use GitHub Issues for blog comments. It’s open source, looks clean, comments are stored on GitHub, and even comes with a dark theme.

Utterances Limitations

  • Readers must have a GitHub account to comment.
    • Utterances supports no other login or authentication mechanisms.
  • For storing comments, Utterances supports only GitHub.
    • GitLab, BitBucket, and so on are not supported.

Implementing Utterances

  1. You will need to have your website hosted on GitHub, in a public repository, in order for utterances to work as intended.
  2. Install utterances app on that repo. Select the above public repo from the drop-down menu that will appear.
    utterances-app-setup.jpeg
    Utterances App Setup
  3. Run the Utterances configuration tool to generate the script configuration. Fill in the requested form and it would generate the custom html which can be copy & pasted into your template.
  • name of the repository : Usually, it will be something like «username»/«username».github.io (or more generally owner/repo)
  • Blog Post ↔️ Issue Mapping: Choose the mapping between blog posts and GitHub issues.
    utterances-blog-post-issue-mapping.jpeg
    Utterances Blog Post Issue Mapping
  • label (optional): as the comments will be managed via GitHub Issue system, you will need to set-up a proper label to identify those issues created by Utterances.
  • theme: your choice of a light or dark theme, according to the overall style of your current blog template.
  1. Copy the Enable Utterances script.
    utterances-enable-script.jpeg
    Utterances Enable Script
  2. Update the layouts/partials/comments.html - Replace everything in it with utterances script code.
1<script src="https://utteranc.es/client.js"
2	repo="prasbhat/prasbhat.github.io"
3	issue-term="title"
4	label="Comments"
5	theme="github-light"
6	crossorigin="anonymous"
7	async>
8</script>
  1. Comments are already enabled in layouts/_default/single.html towards the end, in the Mainroad theme.
1{{ define "main" }}
2<main class="main" role="main">
3	...
4</main>
5{{ partial "authorbox.html" . }}
6{{ partial "pager.html" . }}
7{{ partial "comments.html" . }}
8{{ end }}
  1. That’s it. Now when you refresh the browser, you can see the Comments section available.
    utterances-comments-section.jpeg
    Utterances Comments Section
  2. As mentioned earlier, one drawback of this tool is, it works only with GitHub and user has to login with their GitHub account, before leaving comments.
    • Click on “Sign in wih GitHub”.
    • You will be presented with the GitHub Login page.
    • After you login, you will be able to comment.
      utterances-comments-section-enabled.jpeg
      Utterances Comments Section Enabled
      After adding comments
      utterances-comments-section-2.jpeg
      Utterances After Comments

These are some of the enhancements, I have implemented in my Hugo project, to make it more enjoyable.