The theme I used is PaperMod, and this article uses it as an example.
All paths must use relative paths (do not add a leading slash)!
Table of Contents#
If you want to display a table of contents on the article page, please pay attention to the following configuration:
params:
showToc: true # Globally show table of contents
tocopen: true # Globally expand table of contents (the table of contents is collapsed by default)
Multilingual#
The configuration here can easily go wrong. If you, like me, enjoy creating multilingual blogs, please pay attention to the following configuration:
defaultContentLanguage: zh-cn
defaultContentLanguageInSubdir: true
defaultContentLanguage: zh-cn
- Sets the default language of the website to Simplified Chinese
- Affects the URL structure generated by Hugo
- Determines the language identifier for default content
Do not modify the above configuration unless you really need to change the default language.
defaultContentLanguageInSubdir: true
- Controls whether the default language content is placed in a subdirectory
- true: The default generated path is zh-cn/posts/
- false: The default generated path is posts/
Example:
# When defaultContentLanguageInSubdir: true
public/
├── zh-cn/ # Default language (Chinese) content
│ └── posts/
└── en/ # Other language content
└── posts/
# When defaultContentLanguageInSubdir: false
public/
├── posts/ # Default language (Chinese) content
└── en/ # Other language content
└── posts/
You need to configure the multilingual content directory:
languages:
zh-cn:
languageName: "Simplified Chinese"
contentDir: "content/zh-cn" # content/<lang>
# ... Any multilingual configuration can be written here
en:
languageName: "English"
contentDir: "content/en"
# ...
Under the multilingual configuration, the effective paths for search.md
and archive.md
are:
content/
├── zh-cn/
│ ├── posts/
│ ├── search.zh-cn.md # search.<lang>.md
│ └── archive.md
└── en/
├── posts/
├── search.en.md
└── archive.md
The URLs for the above two can remain generally set in hugo.yaml
:
languages:
zh-cn:
menu:
main:
- identifier: "search"
name: "Search"
url: "search"
weight: 1
- identifier: "archives"
name: "Archives"
url: "archives"
weight: 2
Search#
To support the search function, the following configuration must be made in hugo.yaml
:
outputs:
home:
- HTML
- RSS
- JSON # JSON is key for search support
Fonts#
I want to use Ubuntu Mono for English, HarmonyOS Sans SC for Chinese, and JetBrains Mono for code, so I made the following configuration.
Create themes/PaperMod/assets/css/extended/fonts.css
:
@import url('https://cdn.jsdelivr.net/npm/ubuntu-mono/css/ubuntu-mono.min.css?display=swap');
@import url('https://cdn.jsdelivr.net/npm/harmonyos-sans-font/css/harmonyos-sans.min.css?display=swap');
@import url('https://cdn.jsdelivr.net/npm/jetbrains-mono/css/jetbrains-mono.min.css?display=swap');
body {
font-family: "Ubuntu Mono", "HarmonyOS Sans SC", sans-serif;
}
code, pre {
font-family: "JetBrains Mono", monospace;
}
Code Block Background Color#
The default brightness of the code block background color is very low (very dark), so I modified it.
In themes/PaperMod/assets/css/common/post-single.css
at line 206, you can see that the --code-block-bg
variable determines the background color of the code block:
.post-content pre code {
display: grid;
margin: auto 0;
padding: 10px;
color: rgb(213, 213, 214);
background: var(--code-block-bg) !important;
border-radius: var(--radius);
overflow-x: auto;
word-break: break-all;
}
A global search revealed that themes/PaperMod/assets/css/core/theme-vars.css
has two declarations for this variable:
:root {
...
--code-block-bg: rgb(43, 43, 43);
...
}
.dark {
...
--code-block-bg: rgb(43, 43, 43);
...
}
Changing both to rgb(43, 43, 43)
will suffice.
Comments#
I use Giscus, which is a comment system implemented using GitHub Discussions.
Please ensure:
- The blog repository is public; otherwise, visitors will not be able to view Discussions.
- The giscus app is installed; otherwise, visitors will not be able to comment and respond.
- The Discussions feature has been enabled in the repository.
Then visit the Giscus website, and configure it as required.
After configuration, content like the following will appear under the "Enable giscus" title:
<script src="https://giscus.app/client.js"
data-repo="[Enter repository here]"
data-repo-id="[Enter repository ID here]"
data-category="[Enter category name here]"
data-category-id="[Enter category ID here]"
data-mapping="pathname"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="bottom"
data-theme="preferred_color_scheme"
data-lang="zh-CN"
crossorigin="anonymous"
async>
</script>
Create layouts/partials/comments.html
and copy and paste the obtained <script> tag into it.
Ensure that comments are enabled in hugo.yaml
:
params:
comments: true
Deployment#
After running the hugo -D
command, Hugo will build the static blog in the public
directory. Generally, the public
directory is deleted before each build to ensure that the newly built content is correct.
In this case, I want to deploy only the static blog to the repository, not the entire Hugo framework. So I wrote a Shell script:
@echo off
hugo -D
cd public
git init
git remote add origin git@github.com:<user>/<repo>.git
git checkout -b main
git fetch
git add -A
git commit -m "temp"
git reset --soft origin/main
git commit -m "update %date%"
git push
cd ..
Since it was inconvenient to maintain, I switched to creating a separate source branch and deployment branch within the same repository. Thus:
# Create public branch in the main repository
git checkout --orphan public
git reset --hard
git commit --allow-empty -m "Init public branch"
git push origin public
git checkout main
# Link the public directory to the public branch
git worktree add -B public public origin/public
# Generate the website and push
hugo -D
cd public
git add -A
git commit -m "Push %date%"
git push origin public
cd ..
Combined with the CI/CD provided by Cloudflare Pages, a single script can achieve one-click push updates.
Do not configure baseURL
in hugo.yaml
, as this will cause all deployed unique preview URLs to be redirected to baseURL
.
Example of hugo.yaml
#
This is the hugo.yaml
I used.