Follow Installation doc to install Hugo and PaperMod.

Git Submodule Method is recommended, which keeps your repo independent and tidy by seperating your configs and posts from the theme’s source code.

Notice: Don’t forget to add a .gitignore file in your repo, like this:

1
2
3
4
/public
.DS_Store
.hugo_build.lock
resources/_gen/

Following are the tutorials of configuring PaperMod. You can reproduce the features by simply copy the corresponding code snippets or just clone my github page repo and replace my posts with yours.

Check PaperMod doc and Hugo quick start for more details. PaperMod exampleSite source is also a good start.

Configuration

Home Info

Follow the home info mode doc to show welcome message and social links on home page.

Add following to your hugo.yaml, you can modify as you like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
params:
  homeInfoParams:
    Title: "👋 Welcome to Z'Blog"
    Content: >
      - Hi, A **Software Engineer** here! 🤗

      - Passionate about exploring Linux 🐧, AI 🤖 and software development 💻.      

  socialIcons:
    - name: github
      title: Visit me on GitHub
      url: "https://github.com/figuremout"

More social icons are available in papermod icons.

Code Snippets:

Construct main menu in the top-right corner.

First, you need to specify menu entries and their URL routes in hugo.yaml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
menu:
  main:
    - name: Archive
      url: archives/
      weight: 10
    - name: Search
      url: search/
      weight: 20
    - name: Tags
      url: tags/
      weight: 30
    - name: Github
      url: https://github.com/figuremout
      weight: 40

weight is used to control the order of entries.

Code Snippets:

Tags page will be automatically generated (see hugo defualt taxonomies), while additional works are needed to generate Archive and Search pages.

Archive Page

Create Archive page content/archives.md:

1
2
3
4
5
6
---
title: "Archive"
layout: "archives"
url: "/archives/"
summary: archives
---

Code Snippets:

Search Page

Add following to your hugo.yaml:

1
2
3
4
5
outputs:
  home:
    - HTML
    - RSS
    - JSON # necessary for search

Create Search page content/search.md:

1
2
3
4
5
6
---
title: "Search" # in any language you want
layout: "search" # necessary for search
summary: "search"
placeholder: "placeholder text in search input box"
---

Code Snippets:

Zoom in Image on Click

The issue comment provides a solution using medium-zoom, which works perfectly.

Add this to layouts/partials/extend_footer.html to zoom an image and dim the background on click:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<script src="https://cdnjs.cloudflare.com/ajax/libs/medium-zoom/1.0.6/medium-zoom.min.js" integrity="sha512-N9IJRoc3LaP3NDoiGkcPa4gG94kapGpaA5Zq9/Dr04uf5TbLFU5q0o8AbRhLKUUlp8QFS2u7S+Yti0U7QtuZvQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<script>
const images = Array.from(document.querySelectorAll(".post-content img"));
images.forEach(img => {
  mediumZoom(img, {
    margin: 0, /* The space outside the zoomed image */
    scrollOffset: 40, /* The number of pixels to scroll to close the zoom */
    container: null, /* The viewport to render the zoom in */
    template: null, /* The template element to display on zoom */
    background: 'rgba(0, 0, 0, 0.8)'
  });
});
</script>

Code Snippets:

Demostration: test

Latex Support

Papermod has a guide to setup KaTeX.

Create a partial layouts/partials/math.html. Notice: In order to support $ as delimiter, you need to call the renderMathInElement to config Auto-render Extention as following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css" integrity="sha384-wcIxkf4k558AjM3Yz3BBFQUbk/zgIYC2R0QpeeYb+TwlBVMrlgLqwRjRtGZiK7ww" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.js" integrity="sha384-hIoBPJpTUs74ddyc4bFZSM1TVlQDA60VBbJS0oA934VSz82sBx1X7kSx2ATBDIyd" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
<script>
    document.addEventListener("DOMContentLoaded", function() {
        renderMathInElement(document.body, {

          // customised options
          // • auto-render specific keys, e.g.:
          delimiters: [

              {left: '$$', right: '$$', display: true},
              {left: '$', right: '$', display: false},
              {left: '\\(', right: '\\)', display: false},
              {left: '\\[', right: '\\]', display: true}
          ],
          // • rendering keys, e.g.:
          throwOnError : false
        });
    });
</script>

Include the partial in extend_head.html:

1
2
3
{{ if or .Params.math .Site.Params.math }}
{{ partial "math.html" . }}
{{ end }}

Then you can globally enable KaTex in hugo.yaml as below or manually add math: true in posts’ front matter:

1
2
params:
  math: true

Code Snippets:

Demostration:

1
2
3
4
5
6
Inline math: $E=mc^2$

Block math:
$$
E=mc^2
$$

Inline math: $E=mc^2$

Block math: $$ E=mc^2 $$

Show Lastmod Time as Date

Set date of every post in frontmatter is tooooo troublesome and hard to maintain. Luckily, we can configure dates to show file’s last modification timestamp.

Add this to hugo.yaml:

1
2
3
frontmatter:
  date:
  - :fileModTime # Fetches the date from the content file’s last modification timestamp.

Code Snippets:

Edit link for posts is the “Suggest Changes” button on this page, through which you can access the source file easily.

Add following to hugo.yaml, you should change the URL to your repo that contains the post’s source file:

1
2
3
4
5
params:
  editPost:
    URL: "https://github.com/figuremout/figuremout.github.io/tree/main/content"
    Text: "Suggest Changes" # edit text
    appendFilePath: true # to append file path to Edit link

It will link to $URL/posts/post-name.md.

Code Snippets:

Syntax Highlighter

Using Hugo’s syntax highlighter “chroma” to config the code block’s line number, style and so on.

Code Snippets:

Demostration:

1
2
print("hello")
print("world")

Host on Github Pages

Host your site on Github Pages and setup Github Actions, so that Github will rebuild and deploy your site automatically whenever you push a change. Hugo provides a guide to build the workflow.

Code Snippets:

Render Raw HTML in Markdown

Hugo does not render raw HTML by default. As a result, you cannot embed vedios using <iframe>, superscript using <sup> or insert collapsible sections using <details>, etc. Though you can achieve the same by Hugo Shortcodes, you may prefer the more direct way: Insert pure HTML in Markdown.

Just enable the unsafe option of Goldmark Markdown renderer in hugo.yaml to make it work.

1
2
3
4
markup:
  goldmark:
    renderer:
      unsafe: true

Code Snippets:

Demostration:

Change Content Width

This issue comment provides a nice solution.

Add following to assets/css/extended/theme-vars.css:

1
2
3
:root {
    --main-width: 750px;
}

Code Snippets:

Change Fonts

You can use fonts from Google Fonts.

  1. Find a font on Google Fonts.
  2. Get embed code for Web (several lines of html and css).
  3. Copy the html parts to layouts/partials/extend_head.html.
  4. Copy the css parts to assets/css/extended/blank.css (adjust css selector according to your needs, e.g. body, code, .post-content…).

Code Snippets:

Or download fonts like DroidSansM Nerd Font into static/fonts/, then create assets/css/extended/fonts.css with the following code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@font-face {
    font-family: "DroidSansMNerdFontMono-Regular";
    src: url("/fonts/DroidSansMono/DroidSansMNerdFontMono-Regular.otf");
}

@font-face {
    font-family: "DroidSansMNerdFontPropo-Regular";
    src: url("/fonts/DroidSansMono/DroidSansMNerdFontPropo-Regular.otf");
}

@font-face {
    font-family: "DroidSansMNerdFont-Regular";
    src: url("/fonts/DroidSansMono/DroidSansMNerdFont-Regular.otf");
}

And specify font-family in assets/css/extended/blank.css with the following code:

1
2
3
.post-content {
    font-family: "DroidSansMNerdFontPropo-Regular";
}

View Count

This blog is a great tutorial to count page views and site visits using busuanzi API.

Code Snippets:

Copying and editing the theme code could make things less elegant than before, but it’s a necessary compromise.

Q & A

How to specify image path?

Check this, there are two ways to reference a image in markdown.

My preferred way is:

  • Put all images in static/images.
  • And reference an image by ![img](/images/test.png).

BTW, add #center after image link to center it, see doc.

How to generate posts with desired default frontmatter?

  1. Create archetypes/default.md with the frontmatter template only .
  2. Exec hugo new content content/posts/new.md.