Following with the HUGO topic, there are many customizations that can be applied.
This can differ from theme to theme, but I want to consolidate here a few that found interesting and that I believe can be apply in any theme that you will choose (or maybe create?).
HUGO Shortcodes
Tweaking HTML
I am not a web dev, but…
How to include HTML content
Create /layouts/shortcodes
folder on your HUGO folder.
Then create the file rawhtml.html with the following content:
<!-- raw html -->
{{.Inner}}
Then, you can use it in your posts by using the following logic:
Including Leaflet Map as HTML
For example, this output from leaflet map:
Customize your links
Custom URLs for Posts
Simply include the following parameter in the post configuration:
url: 'your-desired-path'
This will ignore the post-name.md from the file.
How to use nofollow links with HUGO
Add a render-link.html file which is processed (note to self: make sure you have a recent version of Hugo installed). This file is in /themes/your-theme-name/layouts/_default/_markup/ (or potentially somewhere directly too).
- This file is processed whenever a link is rendered, so you might already have something in there.
- Credit for: https://johnmu.com/nofollow-hugo/
Editing the 404 Page
You will find it in your theme folder, under layouts/404.html.
{{- define "main" }}
<div class="not-found">404</div>
{{- end }}{{/* end main */ -}}
With some basic HTML knowledge you can edit that, for example to:
{{ define "main"}}
<main id="main">
<div>
<h1 id="title"><a href="{{ "" | relURL }}">Take me back Home.</a></h1>
</div>
</main>
{{ end }}
Cover Image for your Posts
You can try with
Socialify
If your post content has ana ssociated Github repository, you can create an automatic cover for your post thanks to the fantastic work from https://socialify.git.ci/
Decide the parameters that you want to be visualized and generate the link that will be as the cover - image parameter in the post. Like this:
cover:
image:
https://socialify.git.ci/JAlcocerT/R_Stocks?description=1&descriptionEditable=Shiny%20Dashboard%20that%20displays%20free%20available%20financial%20information.%20%0A%0A&font=Inter&name=1&owner=1&pattern=Solid&theme=Auto
Pretty handy for enhance the content related to our Github Repositories.
Add your Posts Tags
To the POST page
For that you will need to customize the file ’layouts/partials/post_meta.html’ of your theme:
{{- $scratch := newScratch }}
{{- if not .Date.IsZero -}}
{{- $scratch.Add "meta" (slice (printf "<span title='%s'>%s</span>" (.Date) (.Date | time.Format (default "January 2, 2006" site.Params.DateFormat)))) }}
{{- end }}
{{- if (.Param "ShowReadingTime") -}}
{{- $scratch.Add "meta" (slice (i18n "read_time" .ReadingTime | default (printf "%d min" .ReadingTime))) }}
{{- end }}
{{- if (.Param "ShowWordCount") -}}
{{- $scratch.Add "meta" (slice (i18n "words" .WordCount | default (printf "%d words" .WordCount))) }}
{{- end }}
{{- $author := (partial "author.html" .) }}
{{- $tags := (partial "tags.html" .) }}
{{- if $tags }}
{{- $scratch.Add "meta" (slice $author $tags) -}}
{{- else}}
{{- $scratch.Add "meta" (slice $author) -}}
{{- end}}
{{- with ($scratch.Get "meta") }}
{{- delimit . " · " -}}
{{- end -}}
Also, you have to create ’layouts/partials/tags.html’:
{{- $tags := .Params.tags -}}
{{- if $tags -}}
{{- $lastIndex := sub (len $tags) 1 -}}
{{- range $index, $tag := $tags -}}
<a href="/tags/{{ $tag | urlize }}"> {{ $tag }}</a>
{{- if ne $index $lastIndex }} · {{ end -}}
{{- end -}}
{{- end -}}
This has been found thanks to an on going discussion of the PaperMod theme that I am using for the blog, but should be able to operate with other themes as well.
Add your HUGO POST Summary to Archive
Create the file (post_meta.html exists and it will affect what you see in /posts
or /tags
) themes/PaperMod/layouts/partials/post_meta_archives.html with the following (in the last part we make use of .Params.summary):
{{- $scratch := newScratch }}
{{- if not .Date.IsZero -}}
{{- $scratch.Add "meta" (slice (printf "<span title='%s'>%s</span>" (.Date) (.Date | time.Format (default "January 2, 2006" site.Params.DateFormat)))) }}
{{- end }}
{{- if (.Param "ShowReadingTime") -}}
{{- $scratch.Add "meta" (slice (i18n "read_time" .ReadingTime | default (printf "%d min" .ReadingTime))) }}
{{- end }}
{{- if (.Param "ShowWordCount") -}}
{{- $scratch.Add "meta" (slice (i18n "words" .WordCount | default (printf "%d words" .WordCount))) }}
{{- end }}
{{- $author := (partial "author.html" .) }}
{{- $tags := (partial "tags.html" .) }}
{{- if $tags }}
{{- $scratch.Add "meta" (slice $author $tags) -}}
{{- else}}
{{- $scratch.Add "meta" (slice $author) -}}
{{- end}}
{{- with ($scratch.Get "meta") }}
{{- delimit . " · " -}}
{{- end -}}
{{- if .Params.summary }}
{{ with .Summary }}
<div class="post-summary">{{ . }}</div>
{{ end }}
{{- end }}
Modify the Looks
HUGO Main Page: adding pinned posts
In general, you’ll need to
- Add the isPinned tag to the posts that you want to be kept in the main page
---
title: "My Pinned Post"
date: 2023-05-04T00:00:00+00:00
isPinned: true
#other_post_parameters
---
- Modify the layouts/index.html. In my case, I am using PaperMod theme right now and I have the profile mode enabled.
- When going to that index.html file, you will see that under that condition, it ‘redirects’ us to the file layouts/partials/index_profile.html. This is the file in charge of creating the main page of our blog.
Follow these steps:
- Query the pinned posts in your config.yaml file. Add this code at the beginning of the HTML file (before the opening tag):
{{ $pinnedPosts := where site.RegularPages "Params.isPinned" true }}
- Now we have the list of post that mets that condition ready, lets include them in our HUGO main page. To display the pinned posts in the profile widget.
Add the following code right after the buttons div (before the closing tag of the profile_inner div):
{{- if $pinnedPosts }}
<div class="pinned-posts">
<h2>Pinned Posts</h2>
<ul>
{{- range $pinnedPosts }}
<li><a href="{{ .Permalink }}">{{ .Title }}</a></li>
{{- end }}
</ul>
</div>
{{- end }}
This block checks if there are any pinned posts, and if so, creates a div with the class pinned-posts, displays a header “Pinned Posts”, and generates an unordered list with links to the pinned posts.
Better summaries and post descriptions in HUGO
When writing a new post, be sure that you use the following variables:
description: "A great description for your post."
summary: 'A great summary that will appear in the posts view, instead of the automatic initial 70 words of your post.'
If you want to change the default 70 words of summary, use the following variable in the config.yml:
summaryLength: 100 #70
Adding favicons to HUGO
- You can use: https://favicon.io/favicon-converter/ - Follow the steps:
- go to the theme folder
- add a
/static
folder - add the files generated with the website
Use fonts
https://wowchemy.com/docs/getting-started/customization/
How to modify the main page footer
You can hide it by adding to the config.yml
params: hideFooter: false
If you want to customize it:
Modify the resulting .html in public
This is the file that will be in charge of creating the footer that will go to the /public folder when the web will be generated or that you will visualize locally:
- better option: go to ``themes/your_theme/layouts/_default/partials/footer.html
- and edit it accordingly
Add commenting systems to HUGO
Include at themes/your_hugo_theme/layouts/partials
, the following comments.html
These are the Remark42 Files we need to add to HUGO ⏬
{{- /* You can add your own layouts/comments.html to override this file */ -}}
{{- $pageCommentSystems := .Param "pageCommentSystems"}}
{{- if not $pageCommentSystems }}
{{- $pageCommentSystems = site.Params.defaultCommentSystems }}
{{- end }}
{{- $page := . -}}
{{- with site.Params.commentSystems -}}
{{- if $pageCommentSystems.remark42 -}}
{{- with .remark42 -}}
{{- partial "remark42.html" (dict "page" $page "ctx" .) }}
{{- end -}}
{{- end -}}
{{- if $pageCommentSystems.telegramWidget -}}
{{- with .telegramWidget -}}
{{- partial "telegram_widget.html" . }}
{{- end -}}
{{- end -}}
{{- if $pageCommentSystems.disqus -}}
{{- with .disqus -}}
{{- partial "disqus.html" (dict "page" $page "ctx" .) }}
{{- end -}}
{{- end -}}
{{- end -}}
And also add the remark42.html
<div class="comments">
<div class="title">
<span>Comments</span>
<span class="counter"><span class="remark42__counter" data-url="{{ .page.Permalink }}"></span></span>
</div>
<div id="remark42">
</div>
</div>
<script>
var remark_config = {
host: '{{ .ctx.url }}',
site_id: '{{ .ctx.site }}',
components: ['embed', 'counter'],
max_shown_comments: 20,
theme: 'light',
simple_view: true,
admonition: JSON.stringify(['Please subscribe by email to receive reply notifications.']),
};
if (isDarkTheme()) {
remark_config.theme = 'dark'
}
(function() {
// toogle theme callback
const key = 'remark42'
if (!toggleThemeCallbacks.hasOwnProperty(key)) {
toggleThemeCallbacks[key] = (isDark) => {
const remark42 = window.REMARK42
if (!remark42 || !document.querySelector('#remark42')) {
return;
}
if (isDark) {
remark42.changeTheme('light');
} else {
remark42.changeTheme('dark');
}
}
}
// init or reset remark42
const remark42 = window.REMARK42
if (remark42) {
remark42.destroy()
remark42.createInstance(remark_config)
} else {
for (const component of remark_config.components) {
var d = document, s = d.createElement('script');
s.src = `${remark_config.host}/web/${component}.mjs`;
s.type = 'module';
s.defer = true;
// prevent the <script> from loading mutiple times by InstantClick
s.setAttribute('data-no-instant', '')
d.head.appendChild(s);
}
}
})();
</script>
Dont forget to specify in your config.yml
(as child in the params section):
params:
commentSystems: #hugo papermodX
remark42:
url: https://remark42.fossengineer.com
site: site_as_specified_in_remark_yaml
defaultCommentSystems:
remark42: true
FAQ
How to Modify the HUGO generated main page?
You have to modify the theme’s file: layouts/partials/index.html (in your theme it might be called differently - example in PaperMod it is index_profile.html when profile mode is activated).
You can add new features like listing some specific .md content under /content
with:
Tweaking an HUGO main Page ⏬
{{- if $Projects }}
<div class="project-cards">
<h2>Awesome F/OSS Projects</h2>
<ul>
{{- range $Projects }}
<li>
<div class="project-item">
{{ if .Params.icon }}
<img src="{{ .Params.icon }}" alt="{{ .Title }} Icon" class="project-icon">
{{ end }}
<span class="project-title">{{ .Title }}</span> <!-- Project Title -->
<p class="project-description">{{ .Params.description }}</p> <!-- Project Description -->
<a href="{{ .Params.link }}">📖</a> <!-- Hyperlink to Project -->
{{ if .Params.Guide }}
<a href="{{ .Params.Guide }}">📋</a> <!-- Hyperlink to Guide -->
{{ end }}
</div>
</li>
{{- end }}
</ul>
</div>
{{- end }}
The related css will be normally at: assets/css/common/main.css
, but again you might have different file affecting your theme, like in this case .../common/profile-mode.css
How to customize the css for HUGO?
Modifying Archive’s css
Under you theme folder, you should be able to find a similar structure and find the proper css file that affects the archive page: /theme/PaperMod/assets/css/common/archive.css
And in that file, include:
.post-summary {
font-size: 10 px; /* 1.2rem; Adjust the font size*/
color: var(--secondary); /*#c20c0c; Adjust the font color */
margin-top: 0.5rem;
}
How to inject JS in ALL HUGO Posts?
Locate the single.html file in the theme’s layout directory (for example /theme/PaperMod/layouts/_default/single.html). Include the js before the end of the article:
</article>
{{- end }}
{{/* end main */}}
Example: Adding Mailerlite to HUGO Posts
Find the file in the HUGO theme responsible for the posts creation.
In my case with HUGO Paper Mod, it is: theme/PaperMod/layouts/_default/single.html
Then, include the script from MailerLite into the footer (or anywhere you want it to be):
</footer>
<!-- MailerLite Subscription Form Container -->
<div class="ml-embedded" data-form="a-data-dorm"></div>
<!-- MailerLite Universal -->
<script>
(function(w,d,e,u,f,l,n){w[f]=w[f]||function(){(w[f].q=w[f].q||[])
.push(arguments);},l=d.createElement(e),l.async=1,l.src=u,
n=d.getElementsByTagName(e)[0],n.parentNode.insertBefore(l,n);})
(window,document,'script','https://assets.mailerlite.com/js/universal.js','ml');
ml('account', 'an-account-id');
</script>
<!-- End MailerLite Universal -->
{{- if (.Param "comments") }}
{{- partial "comments.html" . }}
{{- end }}
</article>
{{- end }}
{{/* end main */}}
F/OSS to leverage a HUGO Website
F/OSS Alternatives to MailerLite
Self-hosted newsletter and mailing list manager:
- ListMonk
- SendPortal
F/OSS Web Forms for HUGO
Open Source Survey Platform
HeyForm is an open-source form builder that allows anyone to create engaging conversational forms for surveys, questionnaires, quizzes, and polls. No coding skills required.
- You can use NextCloud Forms
- Share them with iframe or Share to anyone with the link
Forms in HUGO with OhMyForm
OhMyForm also has WebHooks
How to Setup OhMyForm ⏬
Just clone and use the provided Docker-Compose:
git clone https://github.com/ohmyform/ohmyform.git
#Step Two: Modify anything you want to in the source.
cd ohmyform
#git submodule update --init
docker-compose up -d
#docker-compose ps
It also have webhooks:
version: "3"
services:
ohmyform:
image: ohmyform/ohmyform
volumes:
# - "./data:/data"
- ohmyform_data:/app/data
environment:
CREATE_ADMIN: "TRUE"
ADMIN_EMAIL: [email protected]
ADMIN_USERNAME: admin
ADMIN_PASSWORD: admin
DATABASE_DRIVER: sqlite
DATABASE_URL: "sqlite:///data/data.sqlite"
MAILER_URI: smtp://local.host
LOGIN_NOTE: "Either login with admin:admin or create your own account to test OhMyForm"
ports:
- "8037:3000"
restart: unless-stopped
volumes:
ohmyform_data:
Create stunning embeddable forms for recruiting, market research, surveys and more.
Forms in HUGO with NocoDB
NocoDB is an open-source no-code platform that allows users to create custom database applications without writing any code.
It provides a user-friendly interface for designing and managing databases, as well as building web-based applications on top of those databases.
https://docs.nocodb.com/views/view-types/form/ https://app.nocodb.com
With the No-code application builder: With NocoDB, users can create web-based applications by defining forms, views, and workflows using a visual drag-and-drop interface. It allows users to create custom pages, configure data input forms, and set up data validation rules without writing code.
How to use NocoDB as (Embedded) Contact Forms with Google SMTP ⏬
<iframe>
class="nc-embed"
src="https://nocodb.noted.lol/dashboard/#/nc/form/f42affl0-25d2-2f31-a90a-8d1996d8ck0l"
frameborder="0"
width="100%"
height="800"
style="background: transparent; border: 1px solid #ddd"
</iframe>
- NocoDB supports WebHooks for automating with other apps - https://docs.nocodb.com/category/webhook, like n8n or Hugging
How to use NocoDB WebHooks together with Cloudflare to Restric Accesses ⏬
-
https://docs.nocodb.com/0.109.7/developer-resources/webhooks/
-
https://developers.cloudflare.com/notifications/get-started/configure-webhooks/
-
https://developers.cloudflare.com/cloudflare-one/policies/access/
-
https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/
This DBTech video was a revelation - Restrict Access to Your Cloudflare Tunnel Applications
Now you can use nocoDB webhooks, to update which emails Cloudflare allows to see specific pages
SelfHost NocoDB with Docker ⏬
https://github.com/nocodb/nocodb https://github.com/nocodb/nocodb/tree/master/docker-compose https://docs.nocodb.com/0.109.7/getting-started/installation/
git clone https://github.com/nocodb/nocodb
cd nocodb/docker-compose/pg
docker-compose up -d
F/OSS Web Analytics for HUGO
- Umami
- Plausible
- Matomo
To Monitor a HUGO Website - You can try Uptime Kuma
F/OSS Commenting Systems for HUGO
We have seen how to use Remark42, but there are other alternatives:
- Cactus Comments (Open Source, Matrix appservice, Docker install)
- Comentario (Open Source, self-hosted, Go/Angular, run locally, in Docker or Kubernetes)
- Commento (Open Source, available as a service, local install, or docker image)
- Isso (Self-hosted, Python)
- Remark42 (Open source, Golang, Easy to run docker)
- Staticman
- Talkyard (Open source, & serverless hosting)
- Utterances (Open source, GitHub comments widget built on GitHub issues)
- Giscus (Open source, comments system powered by GitHub Discussions)