Overview of Hugo/PaperMod, modifying PaperMod, and comparison to al-folio
Introduction
I built my old site (not this one) with Hugo and PaperMod and hosted on Netlify.
My old site is still accessible via https://main–cheerful-mousse-b9d87b.netlify.app, and here’s the GitHub repo. For the rest of this post, I’ll refer to it as my (old) PaperMod site.
In this post, I provide an overview of Hugo and PaperMod and describe the modifications I made to the original theme in setting up my old site. Specifically, my PaperMod_diff page shows diff
s between my site and the original theme in HTML pages, and you should refer to it. Instead of bloating this post with inline code, I’ll let you know the relevant files, and you can check out the diff
s (well-documented, with citations of where I found code from).
I have now switched to Jekyll using the al-folio theme (though the theme matters a lot more than the static site generator, imo). I provide comparisons of PaperMod and al-folio throughout this post.
Why did I switch?
Obviously, something must’ve gone wrong for me to switch. Before I switched, I had kept track of all the changes I made to PaperMod in this post, and I also updated the post a bit. If you’d like to make a PaperMod website and aren’t satisfied with its base functionality, then this post would be pretty helpful for you and save you a lot of time.
On the flip side, this post also serves as a review of PaperMod’s functionality (rather, all the missing functionality). It’s possible to implement these features, as I describe here, but the implementations I found are suboptimal and just not worth the effort, in my opinion.
In short, there are a ton of missing features in PaperMod. Check the table of contents on the sidebar under the My website heading for the important missing features I noticed and implemented or found implementations for. It turns out that implementations of all of these missing features already exist and are submitted in PRs and issues, but the creator of PaperMod rejects the code. I suppose there’s value in keeping PaperMod simple and minimal, but I spent several weeks implementing and searching for implementations of these important features. And several implementations I found are suboptimal.
On the other hand, al-folio already implements all of these features well. Switching over to al-folio took a day of work and just involved messing with the config file and copying over the Markdown content, with some minor tweaks. I hardly tweaked the theme itself at all, and I have found only one minor bug so far.
Before proceeding, I want to preface the rest of this post by saying that the creators and contributors of PaperMod and al-folio are all way more skilled than me and have contributed a ton to the community. I think al-folio is better overall, but both themes are great, and making them obviously took a lot more work and skill than writing a little blog post. I’m just sharing my experience and opinions.
Audience
This post was written with two audiences in mind: people who are new to Hugo and people with Hugo experience. If you’re new to Hugo, then I recommend reading this post from start to finish. If you have experience with Hugo, then I recommend skimming. Specifically, I would read Clone/fork for setup instructions. Then skip over the Hugo/PaperMod overview to get to My website, which describes specific features of my website. Please see the Table of Contents for an overview.
Credit
This post is inspired by Konstantin’s similarly-titled blog post.
Resources
Before proceeding, I’d like to share five excellent resources that I used and reference throughout this post. The top three are crucial because they cover Hugo and PaperMod. The bottom two describe very specific features that I reference in My website, so don’t worry about those yet.
My goal is to make the rest of this post self-contained (and link to brief external resources). If something doesn’t make sense, please use the first three resources.
-
1 Hugo Quick Start
- Super quick to read and follow along, < 5 min.
- 2 Getting Started With Hugo (47:41)
- 3 PaperMod demo site/documentation and its source
- 4 Konstantin’s How to Set Up This Blog
- 5 Check links in Hugo with htmltest
As mentioned earlier, I also created PaperMod diff 6 to show modifications I made to the theme in a readable way. In short, to modify a file from the theme, you create a copy of the file and make edits in the copy, but this makes it hard to see what was modified. So, PaperMod diff shows diff
s between the files.
Setup
First, follow the steps here to install Hugo. You should also have Git installed. 7
Clone/fork
Run these commands.
git clone --recurse-submodules --no-single-branch https://github.com/jesse-wei/jessewei.dev-PaperMod.git
cd jessewei.dev-PaperMod
hugo server
--recurse-submodule
clones the PaperMod submodule.
Additionally, you may clone with --depth=1
to save some disk space.
hugo server
starts up a server for you to view the site.
Why clone/fork?
At this point, you could start from scratch instead of cloning/forking my website. However, resources 1 and 2 already describe how to start from scratch.
So, I’ll cut to the chase and have you clone my website and describe changes I made.
If something doesn’t make sense, then I recommend first reading/watching the resources.
In addition, if you notice some specific feature of my website that I don’t explain, then use inspect element to inspect the code for that feature. Then run grep -ir
in this repo to find the relevant code. -r
makes the search recursive, and -i
makes the search case-insensitive. You can also use VSCode’s code-searching feature with Ctrl/Cmd+Shift+F. Lastly, you can also leave a comment below.
Overview of Hugo and PaperMod
Skim this section or skip to My website if you’re already familiar with Hugo and PaperMod (e.g., if you read/watched the resources).
Repo structure
Please read Hugo’s directory structure (3 min) and the top part of Hugo’s content organization (1 min) for a general overview of Hugo’s directory structure. I’ll describe more in-depth below.
Here’s the structure of my repository. I omit unimportant stuff and stuff I don’t use, and certainly changes will be made, but this is all the important stuff:
jessewei.dev-PaperMod
├── assets Overrides PaperMod/assets. Contains mostly CSS, some JS
│ └── css
├── config.yml Site-wide configuration file
├── content
│ ├── about.md
│ ├── archives.md
│ ├── classes
│ ├── discord.md
│ ├── posts List layout
│ ├── privacy.md
│ ├── projects List layout
│ ├── search.md
│ └── teaching List layout
│ └── act List layout within list layout
├── layouts Overrides PaperMod/layouts
│ ├── _default Layout of entire pages (specifically, the <main> element)
│ │ └── single.html
│ └── partials Layout of components of a page
│ ├── comments.html
│ ├── extend_head.html
│ ├── footer.html
│ ├── header.html
│ ├── index_profile.html
│ └── social_icons.html
├── scripts My scripts
├── static Images, etc.
│ ├── SAPsim_still_cropped.jpg
│ ├── SAPsim_still_full.jpg
│ └── ...
└── themes
└── PaperMod
There are 4 crucial parts of the repo: config
, content
, layouts
and assets
, and static
.
config.yml
This is the configuration file for the website containing all site-wide parameters.
content/
This is the directory where site content (posts) goes.
Site content should be Markdown files.
The front matter of a Markdown file contains metadata about the post. For example, the front matter of this post is
---
title: "Overview of Hugo/PaperMod and Setting Up This Site"
date: 2023-05-14T20:13:59-04:00
draft: false
cover:
image: img/hugo_logo_wide.svg
alt: "Hugo logo"
caption: "Hugo logo"
hidden: false
summary: "This post provides an overview of Hugo (PaperMod theme) and details the steps I took in setting up this website."
tags: ["Hugo", "PaperMod", "Markdown", "HTML", "CSS", "Blog", "Website", "Portfolio"]
---
This information is used to generate the post’s page. It’s quite intuitive what these fields do (check by seeing how something in front matter renders on the page), so I won’t go into detail.
For a list of variables you can use, see [Variables | Front Matter](https://adityatelange.github.io/hugo-PaperMod/posts/papermod/papermod-variables/#page-variables) from PaperMod documentation. |
layouts/
and assets/
The files in these directories override the files in themes/PaperMod/layouts/
and themes/PaperMod/assets/
, respectively. If the path of a file in layouts/
exactly matches that of a file in themes/PaperMod/layouts/
, then your site will use the file in layouts/
instead of the one in themes/PaperMod/layouts/
. Same for assets/
.
Essentially, themes/PaperMod/layouts/
and themes/PaperMod/assets/
specify defaults. If you want to make a change, override the default in your own repo.
layouts/
contains HTML files that specify the structure of pages.
Let’s look at PaperMod/layouts/_default/
.
themes/PaperMod/layouts/_default
├── _markup
├── archives.html
├── baseof.html
├── index.json
├── list.html
├── rss.xml
├── search.html
├── single.html
└── terms.html
baseof
In particular, here’s baseof.html
. Note that double braces { { } }
(without space between braces) are used in the actual code, but I will be using single braces from now on so the code can be correctly rendered in this page.
This is the base template for all pages. Notice it has all parts of an HTML document: <!DOCTYPE html>
, <html>
, <head>
, and <body>
.
It’s mostly HTML. However, note the code in braces { { ... } }
or { {- ... -} }
. This is Go template code. It’s a templating language that Hugo uses to generate HTML.
Note on line 2 that a site variable site.Language
is directly inserted into an HTML attribute. Some site variables are in config.yml
, and others are built-in to Hugo.
Note on line 5 that a partial head.html
is inserted. A partial is an HTML snippet that can be inserted into a page. As we can see here, the partial head.html
(which can be found under layouts/partials/head.html
) is the <head>
code of all pages.
Does this mean all pages have the same <head>
code?
Nope, notice one last thing on line 9: conditionals! By checking the values of some variables, we can conditionally insert HTML code. Lines 9-14 just insert some classes, but it’s also possible to insert entire HTML snippets or partials. So although all pages have the same template for <head>
, the actual <head>
code depends on parameters.
On lines 16 and 20, we see partials defining the header and footer of a page. In the middle is <main>
for the content of a page. All files in _default
except baseof.html
define <main>
.
single
Most pages are singles (layouts/_default/single.html
). For example, this post on my original site is a single.
A portion of single.html
is below.
{- define "main" }
<article class="post-single">
<header class="post-header">
{ partial "breadcrumbs.html" . }
<h1 class="post-title">
{ .Title }
{- if .Draft }<sup><span class="entry-isdraft"> [draft]</span></sup>{- end }
</h1>
{- if .Description }
<div class="post-description">
{ .Description }
</div>
{- end }
{- if not (.Param "hideMeta") }
<div class="post-meta">
{- partial "post_meta.html" . -}
{- partial "translation_list.html" . -}
{- partial "edit_post.html" . -}
{- partial "post_canonical.html" . -}
<!-- Rest of code omitted -->
Notice this code goes in the "main"
block from line 17 of baseof.html
. You could inspect element a single page on my old PaperMod site to confirm. The code is quite intuitive, so you should be able to see how this code (in addition to front matter and site variables) causes certain elements to appear at the top of the page.
Specifying layout of a page
You should rarely have to manually specify the layout
of a page in front matter. Hugo determines whether a page is a single or list by directory structure. Most pages should be singles, of course.
You can see an example of a list layout at my projects page. However, I did not specify this layout manually: It’s automatically a list layout because projects/
has directories but no index.md
file.
content/projects
├── 566
├── leds
├── mips_emulator
├── neuroruler
├── rubiks_541
└── sapsim
I have two pages where I manually set the layout in front matter. One is Search, and the other is Archives.
Here’s the front matter of search.md
, and it’s similar for archives.md
.
---
title: "Search"
layout: "search"
summary: "search"
---
This topic is further described in Content.
static/
The fourth and final important part is static/
. This is where static files, such as images, go.
I don’t have very many images here because I prefer to group images with the post itself in content/
.
Note that after compilation, files in static/
are copied to the root directory /
. So, when accessing a file in static/
, you should prepend a /
to the file path. For example, the image static/1.jpg
should be accessed as /1.jpg
. In practice, I’ve found that the leading /
can often be omitted. Just know that something like /static/1.jpg
won’t work.
Logo
Site logos are configured in two places in the config.
params:
# OpenGraph image displayed when posting site link on socials
# For example, if you post the link to the site in Discord, this image will be displayed
# This image is used with <meta property="og:image" ...> and <meta property="twitter:image" ...>
images: ["logo_outlined_6.png"]
# ...
# Logo and name shown on top left of site
label:
text: "Jesse Wei"
icon: /logo_filled_outlined_6.png
iconHeight: 35
It’s pretty self-explanatory. I do want to show an example of how the website looks when posted in Discord.
Favicons
See the PaperMod documentation. favicon.io is very convenient for generating favicons!
Shortcodes
I want to mention shortcodes. There are times when you need raw HTML (e.g., figure with centered caption, YouTube video embed, etc.), and shortcodes are shortcodes for doing so. Quite a few are built in to Hugo and PaperMod, and they’re very convenient.
Shortcodes are not built-in to al-folio, to my knowledge, however. In al-folio, the convention is just to inline the raw HTML, so that’s what I’ll be doing to replicate the result of the shortcodes (see my old PaperMod site for the actual results). If you inspect the source code, then you’ll see how convenient shortcodes are!
Raw HTML
{< rawhtml >}
<p align="center"><strong>This is raw HTML</strong></p>
{< /rawhtml >}
This is raw HTML
Figure
{ < figure src="img/social_logo.jpg" caption="OpenGraph image Discord" alt="OpenGraph image Discord" align="center">}
YouTube embed
{ < youtube hjD9jTi_DQ4 >}
The YouTube embed looks a lot better in PaperMod than it does in al-folio.
GitHub gist
{ < gist jesse-wei 0b2472f020b41b8767882291c536102c >}
Deploy
Resource 2 describes how to deploy a Hugo site to Netlify. Here’s a timestamp for that portion of the video.
The build process is incredibly simple. In the video, the only command you input for the build process is hugo
.
My build process involves slightly more than just hugo
since I also have to build PaperMod_diff 6. So, I use scripts/netlify. My build command in Site settings > Build & deploy > Build command is chmod +x scripts/netlify;./scripts/netlify
.
You can ignore that unless you also want to set up a PaperMod_diff page.
al-folio comparison
al-folio deployment is easier because it already includes a GH action for deploying to GH pages. You just need to name your repo {your GH username}.github.io and follow some other steps in the README.
However, deploying the site locally on an M1 MacBook was a huge pain in the ass. For some reason, deploying via Docker wasn’t working, which is super weird. Then Ruby and Jekyll installation was not straightforward. I eventually got local deployment to work after following this YouTube video.
My website
Now I’ll describe specific features of my website.
config.yml
The latest version of my config.yml
is here.
I think I use reasonable values, and I use comments to explain decisions I consider non-obvious. I’ll explain some specific decisions I made in this file in the below sections as they come up.
al-folio comparison
I was very confused by the meanings of several parameters in PaperMod’s config.yml
and had to read PaperMod’s documentation about several parameters. Plus, there are some super weird things that I had to modify. For example, my /teaching
page had the page title Teachings
even though the URL was "teaching"
, which was super confusing. After Googling, it turns out I had to set pluralizeListTitles
to false
, but this parameter doesn’t even exist in PaperMod’s base config.yml
? In addition, this is obviously a feature that should be off by default, so I’m not sure why it’s enabled by default.
al-folio’s config.yml
is commented super well, and I had no issues.
PaperMod diff
I created PaperMod diff 6 using the scripts in scripts/. diff.py
runs diff
between corresponding files, helpers/generate_directory_index_caddystyle.py
creates index.html
files recursively, and build
wraps diff.py
to deploy its output to Netlify (see Deploy). helpers/cd.py
is also used.
Do note that content/posts/papermod_diff
is gitignored. This is because if it weren’t, then the content there would change and be shown on GitHub every time I modify assets/
and/or layouts/
, which is redundant and would make the commit history harder to read. My solution (gitignore the folder and generate it during the build process in Netlify) is a bit roundabout, but it’s already implemented and works well.
Content
This section is a continuation of Specifying layout of a page.
Let’s look more closely at the structure of content/teaching
, which is a list layout.
content/teaching
├── act List layout within list layout
│ ├── _index.md Note, _index.md, not index.md!
│ ├── binary
│ ├── desmos
│ ├── eulers_formula
│ ├── ...
├── comp110
│ ├── img
│ └── index.md
├── comp210
│ ├── img
│ └── index.md
└── comp311
├── img
├── index.md
└── review
My Teaching page has a list layout because teaching/
doesn’t have an index.md
. The comp110/
directory is a single because it has an index.md
. It’s accessible by /teaching/comp110. It also contains an img/
directory that’s accessible from index.md
. The images could go in /static/
, but I prefer bundling them with the page.
It’s possible to have a list layout within a list layout, and /teaching/act is an example. However, notice act/
must have an _index.md
file (note the underscore) since it’s a non-leaf.
See Page Bundles for more details.
al-folio comparison
Honestly, this was (and still is) a bit confusing to me. I can see how it is more organized, but I don’t see why it’s necessary.
al-folio’s directory structure feels just like that of a raw HTML and CSS website and was much easier to get used to.
\(\LaTeX{}\)
I enabled \(\LaTeX{}\) via KaTeX in layouts/partials/extend_head.html
.
I followed Math Typesetting from PaperMod documentation. Specifically, the code in extend_head.html
is mostly from Issue #236.
I modified the condition for loading the KaTeX script. The site param math
must be true. Then KaTeX will be loaded by default in all pages. Setting the local param math
to false
in front matter will cause that page to not load KaTeX.
I think having to opt-in is super annoying, so I’d rather enable it globally and be able to opt-out.
al-folio comparison
al-folio uses MathJax by default. As shown here, MathJax is on par or faster than KaTeX. In my experience, MathJax is also less restrictive.
Comments
I enabled comments using giscus.
I followed the directions on the giscus site to install giscus in my repo and pasted code from the giscus website into layouts/partials/comments.html
. I also added comments: true
to config.
As you can see, there are comments at the bottom of almost every page. PaperMod automatically disables comments in the index profile, search, and archives layouts. I manually disabled comments in my Privacy policy page in the front matter with comments: false
.
Comments show up in GitHub Discussions. Make sure to enable Discussions in your GitHub repo.
However, the comment box does not automatically change color on theme toggle if all you do is add the script. I found an implementation online for it, and it’s in layouts/partials/comments.html
.
al-folio comparison
al-folio implements giscus (and Disqus, deprecated) by default. The only change needed is some configuration in config.yml
. In addition, the comment box automatically toggles color when the theme is toggled.
Social icons in footer
I added social icons to the footer, as in resource 4. I sort of follow what it describes but make some of my own adjustments.
As described there, adding social icons to footer messes with CSS spacing values. For example, a scrollbar appeared on the homepage and Search page (haven’t solved this and don’t plan to) even though there’s enough room for both header and footer to be visible without scrolling. This issue is described more in-depth in resource 4, under problem 2.
In short, I modified CSS in 4 files. layouts/partials/footer.html
, layouts/partials/social_icons.html
, assets/css/core/theme-vars.css
, and assets/css/common/profile-mode.css
. The comments in each file describe the changes I made. Most comments in social_icons.html
are for htmltest, described below, so ignore those for now.
I disabled footer social icons on the homepage because the homepage already has social icons.
al-folio comparison
I didn’t bother with this since al-folio puts social icons in the footer of the homepage by default. That’s fine with me.
Other footer changes
Beyond that, I made some other minor changes to the footer.
I added the separator character • between phrases in the footer.
The links were originally like this:
Powered by
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
<a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
I removed target=_blank
and rel="noopener noreferrer"
because links should not usually open new tabs.
I added a privacy policy page and a link to it in the footer.
Lastly, I removed “Powered by Hugo and PaperMod” in the homepage specifically to keep it minimal.
al-folio comparison
It’s much easier to change the text of the al-folio footer because you need only edit config.yml
.
However, it seems that all external links open in new tabs in al-folio. Personally, I don’t like that, but I get that the purpose is to get the user to stay on your site. It’s fine with me since the behavior is consistent, but I might end up changing this.
Single
I slightly modified layouts/_default/single.html
. I moved the ToC above the cover. Notice on this page that the ToC is above the cover image.
Links are Carolina blue on hover
This was just basic CSS.
I modified CSS in the following CSS files in assets/css/common/
: archive
, footer
, header
, main
, post-entry
, and post-single
.
For example, main.css
has these important lines:
/* Change color on hover */
a:hover {
color: var(--carolina_blue);
}
a.anchor:hover {
color: var(--carolina_blue) !important;
}
svg:hover {
color: var(--carolina_blue);
}
For modifications, look for comments and the variable carolina_blue
. Check PaperMod diff.
Since I made links blue on hover, I removed underline on hover (the link is still underlined if it had an underline before hovering though).
al-folio comparison
al-folio colors links and underlines on hover by default. All I did was change the theme colors to UNC blue in _sass/_variables.scss
and _sass/_themes.scss
.
Syntax highlighting via Chroma
I disabled highlight.js (default) and enabled Hugo Chroma following the steps in PaperMod documentation. This required a few changes in config.yml
and assets/css/extended/*.css
.
I disabled line numbers by default in config.yml
for readability. Most code blocks you’ve seen so far have not had line numbers.
However, you can enable line numbers for a specific code block, as shown in the baseof code block, by adding {lineNos=true}
to the code block. 8
It was very easy to install just one Chroma theme. However, I also wanted the code theme to toggle when the theme toggles. This should’ve been decently easy because all I had to do was a second stylesheet with a dark code theme and add .dark
to the class names. However, I ran into a lot of issues with the light theme CSS overriding the dark theme CSS for most combinations of themes. It could’ve been a fault in my implementation, but without changing anything, the specific combination of pygments (light) and dracula (dark) didn’t have any issues, so I’m not sure what was going on.
Plus, there’s a second issue. Line numbers on code blocks look weird.
al-folio comparison
Everything works well by default! I changed $code-bg-color-light
in sass/_variables.scss
, but I think that’s it.
However, Hugo’s code syntax highlighter supports go-html-template
(I just specify html
or text
in this post) and arduino
, whereas Jekyll’s doesn’t. In addition, in PaperMod, I didn’t have to convert double braces to single braces inside code blocks like I had to do in this post.
Table of Contents
This one is quite important to me but is horrible to implement on PaperMod.
On this post, notice the ToC on the side (if your screen is wide enough) that automatically changes color to show you where you are in the post. In addition, since there’s not enough room to show all the headings, it only shows all the top-level headings and expands the lower-level headings of the heading you’re currently on. I think this is a very good feature for organization too since you don’t get much out of seeing lower-level headings if you’re not reading that section.
There’s a fork of PaperMod called PaperModX that roughly implements this. However, it is not a good implementation, and that’s the best implementation I found (compared to two others in a PaperMod PR and a PaperMod issue). That implementation will show all headings and will display a scrollbar (such as on this page in my PaperMod website) if there are too many headings. It does highlight the active heading, but if there’s a scrollbar, then it won’t scroll down when you get to the bottom, and the active element feature will then break completely. GH issue with more information.
If you’re somehow still interested in implementing this feature in PaperMod, then the relevant code is in assets/css/common/post-single.css
(for putting the ToC on the side and hiding it on small screens), layouts/partials/footer.html
(for a short script - I’m not sure what it does), and layouts/partials/toc.html
(adds a few classes to the toc
div and the script for scrolling and keeping track of the active ToC element). Check PaperMod diff 6.
al-folio comparison
The Bootstrap ToC plugin just works! See the documentation.
The only thing I would change is that on small screens, the side ToC (if enabled) disappears, and there’s nothing to replace it. In the implementation described above, if there’s not a side ToC, then the ToC is at the top of the post (as in normal PaperMod).
I did check what happens with the Bootstrap ToC when there are enough headings to fill the screen by resizing my window. There is no scrollbar, and the ToC just overflows the screen and is cut off. However, realistically speaking, this should never occur, and even if it does, the top-level headings will still be shown.
Hamburger/responsive menu
There should be a hamburger menu for small screens. Several people asked for an implementation of this, but Aditya refuses to merge the change. What’s funny is he implemented it himself and sent the relevant code in Discord but chooses not to merge it into the repo…?
Here’s the commit where I copied in the code, and here’s the relevant issue.
al-folio comparison
You’ll never guess…
al-folio supports this by default. In addition, al-folio also supports dropdown menus and allows you to choose between sticky and fixed header and footer.
Miscellaneous bugs and shortcomings
PaperMod
The scrollbar is bugged on Safari. More information and a fix. This is a problem with the original theme.
Link underlines either disappear or turn the wrong color on theme toggle. More information, and I have not found a solution for this. This is a problem on PaperMod’s site too.
This isn’t really a bug, but in PaperMod, if you use a footnote more than once, then the footnote at the bottom of the post will just specify ↩ ↩ ↩ …, one arrow for each footnote reference. However, al-folio specifies ↩ ↩2 ↩3 …
al-folio
Have found only one bug! So far… 🤞
On the sidebar ToC, at least with a sticky navbar, if you click a heading, then the page will scroll such that the heading is at the top of the page, and the navbar above that. However, the active ToC element probably won’t be the heading you clicked on because the sticky navbar above takes up some space, so the script thinks the active element is the heading above the one you clicked on.
This isn’t a bug, but I would like it if the side ToC ignores the automatically-generated heading “Enjoy Reading This Article?”
Google Analytics
For Google Analytics, just add your Google Analytics tag to googleAnalytics
in the config. For example, mine has googleAnalytics: G-Q603T56FWT
.
PaperMod automatically uses the Google Analytics script if env
is production
(default). See the bottom of layouts/partials/head.html
:
{- /* Misc */}
{- if hugo.IsProduction | or (eq site.Params.env "production") }
{- template "_internal/google_analytics.html" . }
{- template "partials/templates/opengraph.html" . }
{- template "partials/templates/twitter_cards.html" . }
{- template "partials/templates/schema_json.html" . }
{- end -}
al-folio comparison
al-folio also has Google Analytics by default.
CI
I added a GH workflow for checking links in my site and spellcheck. This is not directly related to PaperMod and al-folio.
See .github/workflows/ci.yml
and its configuration file .github/.htmltest.yml
. This follows resource 5, with some modifications. In particular, I want to note that I run my scripts/build
in ci.yml
instead of just hugo
, as in the original file.
Behavior
Here is the intended behavior of the htmltest job after making the modifications below.
If an internal link (e.g., a page or image) doesn’t work, the workflow will fail, causing a red X to appear on GH Actions.
If an external link doesn’t work, htmltest will warn, but the workflow will not fail. That is, an external link could be “broken,” and a green checkmark will be shown on GH Actions. This is fine because when using a lot of external links, it’s unlikely that all will work in any single run. There could be a timeout or non-200 HTML response code, etc.. Getting a red X when just a single external link breaks is annoying. htmltest does still warn, so I manually check GH actions every now and then.
Getting rid of garbage output
There was originally >100 lines of garbage output. htmltest complained that the site logo’s link at the top left had no alt text, and my LinkedIn link in social icons in the footer returned non-OK exit status 999. Since the header and footer are in all pages, this caused a lot of errors, which made the output unreadable.
I fixed this in layouts/partials/header.html
by adding non-empty alt text to the logo and in layouts/partials/social_icons.html
by excluding the LinkedIn link from htmltest using the data-proofer-ignore
attribute, as specified in htmltest’s README.
The top 3 links are ones I want to keep even though they don’t actually work. So I manually ignored them in the post (not layouts/
) using the data-proofer-ignore
attribute in rawhtml. 9
And the #center
thing is how you can center an image in Markdown syntax in PaperMod. #center
also gets appended to an image URL if you use align="center"
in figure shortcode. But since this causes htmltest to freak out, I added this to .htmltest.yml
:
IgnoreURLs:
# Ignore <img src="*#center"> for centered images in PaperMod, which would cause "hash not found"
# This is suboptimal because we ideally want to check the image URL without the #center suffix
# Match internal image path ending in #center
- .*\.(apng|gif|ico|cur|jpg|jpeg|jfif|pjpeg|pjp|png|svg)#center$$
# Match external image URL ending in #center
- (https://|http://|www\.).*\.[A-Za-z]+#center$$
As you can tell by the comments, this is suboptimal and can lead to false negatives. I can think of two solutions.
- Modify htmltest to ignore specific hashes but check the rest of the URL 10
- Modify PaperMod to center the image without appending
#center
Make GH Actions display red X on failure
Instead of continue-on-error: true
from resource 5, I use if: always()
.
- name: Test HTML
# https://github.com/wjdp/htmltest-action/
uses: wjdp/htmltest-action@master
with:
config: ./.github/.htmltest.yml
- name: Archive htmltest results
# Archive result even if Test HTML fails
# Use if: always() instead of continue-on-error, as in the original file
# Source: https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct
if: always()
if: always()
will cause logging to occur even if Test HTML fails. continue-on-error: true
does the same. However, continue-on-error: true
would cause GH Actions to display a green checkmark when Test HTML fails, which is misleading.
IgnoreExternalBrokenLinks
I added this to .htmltest.yml
:
# This does not "ignore" the broken links, but it does not fail the action
# From the htmltest README:
# When true produces a warning, rather than an error, for broken external links.
IgnoreExternalBrokenLinks: true
With a lot of external links, it’s unlikely that all external links will work during any one run. Maybe there’ll be a timeout or bad HTML response code, etc.
Conclusion
There are definitely some other modifications I made to PaperMod that I didn’t describe here, but these are the major points.
I think this post pretty much confirms 100% that, at the moment, Jekyll + al-folio is better than Hugo + PaperMod. Looking into the future, however, Hugo is growing a lot faster than Jekyll is (and imho, it overall does feel better than Jekyll). I can’t be sure if I made an optimal long-term choice, but al-folio is really dang good, and I don’t think I’ll have to completely refactor my website again any time soon.
If you’re using PaperMod, then I hope this post makes it easy for you add some of the necessary features. However, whether you’re using PaperMod or deciding whether to use it or anything else, I hope you consider al-folio!
-
PaperMod demo site/documentation and its source ↩
-
I assume you already do, surely. ↩
-
You might also be able to enable it by default in a specific post by adding it to front matter, but this didn’t work for me. ↩
-
TODO: Create shortcode for a link with
data-proofer-ignore
attribute. ↩ -
This would ignore any URL with
#center
suffix, not just image URLs. ↩
Enjoy Reading This Article?
Here are some more articles you might like to read next: