Leapcell: The Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis
Introduction to Common Usage Techniques of Hugo
Hugo uses the open-source goldmark as the Markdown parser, which is compatible with GitHub.
Introduction
Hugo is a static website page generation tool written in Golang, and its efficiency is much higher than that of Jekyll written in Ruby. You can directly download the binary package from Github, and after decompression, add it to the PATH environment variable to use it.
It is recommended to install the hugo - extended version, which supports the SCSS function and is suitable for theme development. In addition, many extensions have been implemented through goldmark, and the most commonly used one is the task list. For the detailed list, you can refer to the introduction in MarkdownGuide. Hugo can be highly customized, and it tries to be compatible with the Markdown syntax during design.
Basic Usage
- Customize the Page through the Theme: There are many themes to choose from, which can be viewed at themes.gohugo.io. Take hugo - geekdoc as an example. After downloading, directly put it in the themes directory of the project.
- Check if the Installation is Successful:
hugo version
- Create a New Project in the Current Directory:
hugo new site hugo
- Add the theme template to the themes directory, and add theme="doks" in the configuration file config.toml, or start it with the --theme hyde parameter:
git clone --depth 1 --recursive https://github.com/h - enk/doks.git themes
- Create an Article:
hugo --verbose new post/create - hugo - blog.md
- Start the Service:
hugo server --buildDrafts --bind="0.0.0.0" --port=38787
- Generate static files (including drafts), and save them in the buildDir directory, which is public by default:
hugo -D
Configuration Files
By default, configuration files such as hugo.toml, hugo.yaml, and hugo.json in the root directory are used. You can also specify the configuration files in the way of --config a.toml,b.toml. However, it is recommended to use a directory, which is the config directory by default, and can be modified using the configDir configuration item in the configuration file.
hugo.toml
config/
|-_default/
| |-hugo.toml
| |-languages.toml
| |-menus.en.toml
| |-menus.cn.toml
| `-params.toml
|-develop/
| |-hugo.toml
| `-params.toml
`-production/
`-hugo.toml
The first layer in the directory is the environment, including the _default default configuration, and a production directory is also commonly configured. For example, when starting with --environment production, the configuration in _default will be merged with that in production, and it can be checked in the template in the following way:
{{ if eq hugo.Environment "production" }}
<div> Production Mode </div>
{{ else }}
<div> Development Mode </div>
{{ end }}
The second layer corresponds to the top level of the configuration items. Commonly, [Params] corresponds to params.toml, and [Menu] corresponds to menu.toml, including different languages.
Basic Concepts
Section
A collection of pages defined based on the content directory structure. The first-level subdirectories under this directory are all sections. If you want a subdirectory to be a section, you need to define an _index.md file in the directory, and in this way, all sections form a section tree.
content/
`-blog/ <-- Section, because it is a subdirectory of content
|-funny - cats/
| |-mypost.md
| `-kittens/ <-- Section, because it contains _index.md
| `-_index.md
`-tech/ <-- Section, the same as above
`-_index.md
In addition to classifying content through Section, Type customization is also allowed. If there is no Type in the page, then the value corresponding to Section will be used by default. When using it, you can refer to the following lookup order. It can be seen that the template Type has a higher priority than Section, allowing for better customization. You can also handle different page types, including page, section, term, home, taxonomy, etc., that is, the.Kind variable. You can refer to the introduction in the official Methods Kind.
Templates
Hugo uses the html/template library of GoLang as the template engine, which is divided into three types of templates:
- single: Used for rendering a single page.
- list: Renders a set of related content, such as all the content in a directory.
- partial: Can be referenced by other templates and serves as a template-level component, such as the page header and page footer.
Among them, baseof.html serves as the root template for different Sections, and there is a template lookup mechanism. If a template that completely matches the content cannot be found, it will move up one level and search from there. The lookup rules for the basic template baseof.html are as follows:
- /layouts/section/-baseof.html
- /themes//layouts/section/-baseof.html <--- Templates for different Types
- /layouts//baseof.html
- /themes//layouts//baseof.html
- /layouts/section/baseof.html
- /themes//layouts/section/baseof.html <--- Templates for different Sections
- /layouts/_default/-baseof.html
- /themes//layouts/_default/-baseof.html
- /layouts/_default/baseof.html
- /themes//layouts/_default/baseof.html <--- Default value
In the template, the Partials module is introduced through {{ partial "xx" . }}
, and the corresponding page information in the module can be viewed through {{ . }}
. In addition, parameters can be added in the following way: {{ partial "header.html" (dict "current" . "param1" "1" "param2" "2" ) }}
.
In addition to the above way of introducing Partials, you can also customize a module in different types (such as single, list, etc.) through {{ define "main" }} ... {{ end }}
, and then use it in the way of {{ block "main" . }} ... {{ end }}
.
Variable Reference
In the template, variables are referenced in the way of {{ xxx }}
, and the ways to use variables are as follows:
- Global Configuration: For example,.Site.Params.titile corresponds to the [Params] in hugo.toml or the configuration in config/_default/params.toml.
-
Page Parameters: They can be specified at the beginning and referenced in the way of
.Params.xxx
. -
Other Parameters: They include some built-in parameters and can be used directly, such as
.Title
,.Section
,.Content
, and.Page
. -
Localization Parameters: Commonly, they are specified by
i18n "global - identifier"
or converted byi18n .Site.Params.xxx
. -
Using Functions: For example,
hugo.Environment
,hugo.IsExtended
, etc. For others, you can refer to the Functions content.
In addition to the above variables, data files in formats such as json, yaml, toml, and xml can also be saved in the data directory and referenced in the template in the way of .Site.Data.xxx
.
Basic Syntax
The template is wrapped by {{ }}
, and the content inside is called an action (Action), which generally includes two types:
- Data Evaluation: It will be directly output to the template, including directly using variables.
- Control Structure: It includes conditions, loops, functions, etc.
In addition, you can control whether to wrap each line. It is controlled by -
. For example, {{- -}}
means that neither the start nor the end will wrap, but it can also be compressed at the end.
----- Comment
{{/* comment */}}
----- Access existing variables, custom variables
{{ .Title }}
{{ $var }}
{{ $var := "Value" }}
{{ $var := `Hello
World` }}
Slice VS. Map
Slice corresponds to the array, and the common operations are as follows:
{{ $fruit := slice "Apple" "Banana" }}
{{ $fruit = append "Cherry" $fruit }}
{{ $fruit = append $fruit (slice "Pear") }}
{{ $fruit = append (slice "Cherry" "Peach") $fruit }}
{{ $fruit = uniq $fruit }}
{{ range $fruit }}
I love {{ . }}
{{ end }}
{{ range $index, $value := $fruit }}
{{ $value }} or {{ . }} is at index {{ $index }}
{{ end }}
{{ $first := first 2 $fruit }}
{{ $last := last 3 $fruit }}
{{ $third := first 3 $fruit | last 1 }}
{{ $third := index $fruit 2 }}
The usage of the dictionary is as follows:
{{ $hero := dict "firstame" "John" "lastname" "Lennon" }}
{{ $hero = merge $hero (dict "birth" "1940") }}
{{ $hero.firstame }}
{{ $firstname := index $hero "firstname" }}
{{ range $key, $value := $hero }}
{{ $key }}: {{ $value }}
{{ end }}
{{ $basis := "lastname" }}
{{ if eq $relation "friend" }}
{{ $basis = "firstname" }}
{{ end }}
Hello {{ index $hero $basis }}!
{{ range slice "firstname" "lastname" }}
{{ . }}: {{ index $hero . }}
{{ end }}
When using it, you can judge the specific type through {{ if reflect.IsSlice $value }}
or IsMap
.
Logical Judgment
The if
statement is used to judge the truth or falsehood of a certain value, but it is recommended to use with
, and at this time, the context will be rebound within the scope.
{{ if .IsHome }} xxx {{ end }} // It will be called when IsHome is true, otherwise use not
{{ if eq .Title "Home" }} xxx {{ end }} // Judge whether the variables are equal, and ne for not equal
{{ if and .IsHome .Params.show }} xxx {{ end }} // Multiple conditions are met at the same time, or for one of the conditions to be met
{{ if strings.Contains "hugo" "go" }} xxx {{end}} // Judge whether it contains the specified string
// The following two ways are equivalent, and it will be skipped if it is empty
{{ if isset .Params "title" }}
<h4>{{ index .Params "title" }}</h4>
{{ end }}
{{ with .Params.title }}
<h4>{{ . }}</h4>
{{ end }}
// But if can use the else if statement
{{ if (isset .Params "description") }}
{{ index .Params "description" }}
{{ else if (isset .Params "summary") }}
{{ index .Params "summary" }}
{{ else }}
{{ .Summary }}
{{ end }}
// The following is a slightly more complex logic
{{ if (and (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")) }}
<div class="caption {{ index .Params "attr" }}">
{{ if (isset .Params "title") }}
<h4>{{ index .Params "title" }}</h4>
{{ end }}
{{ if (isset .Params "caption") }}
<p>{{ index .Params "caption" }}</p>
{{ end }}
</div>
{{ end }}
If the description attribute is set in Param, then the description content of Param will be output, otherwise the content of Summary will be output.
{{ with .Param "description" }}
{{ . }}
{{ else }}
{{ .Summary }}
{{ end }}
Iteration
For dictionary data, it can be traversed through {{ range $idx, $var := .Site.Data.xxx }}
, and for arrays, it can be traversed in the way of {{ range $arr }}
. Also taking the above Data as an example, you can sort, filter, and obtain data in the following ways.
// Here, the context accesses the array elements. To access the global context, you need to use $. to access
{{ range $array }}
{{ . }}
{{ end }}
// You can declare variables and element indexes
{{ range $val := $array }}
{{ $val }}
{{ end }}
{{ range $idx, $val := $array }}
{{ $idx }} -- {{ $val }}
{{ end }}
// Declare variables for the indexes and values of map elements
{{ range $key, $val := $map }}
{{ $key }} -- {{ $val }}
{{ end }}
// When the passed parameter is empty, the else statement will be executed
{{ range $array }}
{{ . }}
{{else}}
// It will only be executed when $array is empty
{{ end }}
In addition, you can also use the following ways:
<ul>
{{ range sort .Site.Data.books.fiction "title" }}
<li>{{ .title }} ({{ .author }})</li>
{{ end }}
</ul>
{{ range where .Site.Data.books.fiction "isbn" "978 - 0140443530" }}
<li>{{ .title }} ({{ .author }})</li>
{{ end }}
{{ index .Site.Data.books "historical - fiction" }}
In this way, you can filter according to different variables, and the same is true for built-in variables such as .Site.Pages
.
The following is the processing of conditional filtering:
{{- if and (isset .Params "math") (eq .Params.math true) }}
{{- end -}}
Filtering Pages
The following is to first filter the data of the current Section, and the page needs to set the class: "page" option. First, it aggregates according to the year, and then sorts in reverse order according to the date, and displays the date and the corresponding title information.
{{ $blogs := where (where .Site.Pages "Section" .Section) "Params.Class" "==" "page" -}}
{{ range $blogs.GroupByDate "2006" "desc" }}
<h1>{{ .Key }}</h1>
<ul>
{{ range .Pages.ByDate.Reverse }}
<li><span>{{ .Date.Format "2006 - 01 - 02" }}</span> <a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
{{ end }}
</ul>
{{ end }}
The available variables on the page can be viewed through Page Variables, and if you directly print through {{ . }}
, it will display the file path.
Other commonly used usage examples are as follows:
{{ range .Data.Pages }} // Traverse Data.Pages
{{ range where .Data.Pages "Section" "blog" }} // Traverse Data.Pages and filter the data with Section as blog
{{ range first 10 .Data.Pages }} // Traverse Data.Pages and take the first 10 pieces of data
{{ range last 10 .Data.Pages }} // Traverse Data.Pages and take the last 10 pieces of data
{{ range after 10 .Data.Pages }} // Traverse Data.Pages and take the data after the 10th piece
{{ range until 10 .Data.Pages }} // Traverse Data.Pages and take the data before the 10th piece
Short Codes
ShortCodes are mainly used to handle some processing logic that is not convenient to represent in Markdown, thus omitting the writing of some original html code. The official provides some default implementations, such as links to some video websites, relref, etc., and the source code can be referred to on Github.
Suppose there is a foobar ShortCode, which can be used in the following way. Note the way of wrapping parameters. Currently, a better way to prevent rendering has not been found.
{{ foobar "foo" "bar" }}
Some short codes
{{ /foobar }}
There are several ways to obtain the above parameters in the ShortCode template: obtain them through with .Get 0
, which is the simplest and most direct; or obtain them through index .Params 0
, and the content inside can be read through the .Inner
method, and it is required to be called. In addition, you can also refer to some examples in Hugo ShortCodes.
Commonly Used Functions
In the template, it can be referenced in the way of {{ with .Site.Data.Resume . }} {{ .SomeData }} {{ end }}
.
Advanced Usage
Static Files
Including images, CSS, JavaScript, etc., which are usually existing files, such as third-party libraries Bootstrap, FontAwesome, etc. When referencing, they need to be placed in the static directory, and in the template, they need to be placed in the corresponding directory, and they will be automatically copied.
It can be referenced in the way of {{ "css/bootstrap.min.css" | absURL }}
. At this time, when accessing http://foobar.com/css/bootstrap.min.css, it will be mapped to the static/css/bootstrap.min.css file.
Mounts
You can manage third-party JS packages through npm, but at this time, you need to configure it through module.mounts in the configuration file.
[module]
[[module.mounts]]
source = "node_modules/katex/dist"
target = "static/katex"
Then in the template, it can be used in the following way:
<script type="text/javascript" src="{{ "katex/katex.min.js" | absURL }}"></script>`
<link rel="stylesheet" href="{{ "katex/katex.min.css" | absURL }}"/>
CSS
Since version 0.43, Hugo has supported the compilation of SASS. However, the source files can only be placed in the /assets/scss/ or /themes//assets/scss/ directory. Then, it can be introduced in the following way:
{{ $opts := dict "transpiler" "libsass" "targetPath" "css/style.css" }}
{{ with resources.Get "sass/main.scss" | toCSS $opts | minify | fingerprint }}
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
{{ end }}
Use resources.Get to obtain the content of the SCSS file, and then use the pipeline to compile, compress, and generate a fingerprint. This can add a hash file name to the generated file, so that the latest CSS can be pulled from the CDN instead of the cached old file. In addition, in addition to the above configuration options for compiling CSS, you can also refer to the following:
{{ $opts := (dict "outputStyle" "compressed" "enableSourceMap" true "includePaths" (slice "node_modules")) -}}
Code highlighting can be generated through the following command, and examples can be referred to in Style Longer and Style.
hugo gen chromastyles --style=monokai > syntax.css
Note that the configuration parameter codeFences=true should be set, otherwise information such as line numbers will be displayed in the form of a table, resulting in abnormal display.
JavaScript
Similar to CSS, JS scripts can be introduced in the following way:
{{ $params := dict "api" "https://example.org/api" }}
{{ with resources.Get "js/main.js" }}
{{ if hugo.IsDevelopment }}
{{ with . | js.Build }}
<script src="{{ .RelPermalink }}"></script>
{{ end }}
{{ else }}
{{ $opts := dict "minify" true "params" $params }}
{{ with . | js.Build $opts | fingerprint }}
<script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"></script>
{{ end }}
{{ end }}
{{ end }}
In the script, parameters can be referenced in the way of import * as params from '@params';
, and React code can even be introduced through the Shims method. For more functions, you can refer to Hugo JS.
Image Rendering
Customizing the image format in Hugo is a bit troublesome. It does not support the way like {: width="420"}
. Since it supports directly using html, it can be configured in the following way:
<img src="picture.png" alt="some message" width="50%" />
You can customize the alignment of the img in the css, but at this time, only one alignment can be used. In addition, the official provides the shortcodes code of figure
, which can be used, but it will cause compatibility problems on different platforms.
There is another way. Customize the image rendering method in layouts/_default/_markup/render - image.html
, and then use it in a way like 
, but the supported parameters need to be configured in the above file.
For more other rendering Hooks, you can refer to the Render Hooks content.
Data Transfer
Data can be transferred through Scratch, which is used to transfer data between Page and ShortCodes. If you want to use temporary data transfer in the template, you can create a new one through newScratch
. Take the Scratch automatically generated by Hugo as an example below. .Page.Scratch
and .Scratch
have the same function:
{{ .Scratch.Set "hey" "Hello" }} # It can also be 3 or (slice "Hello" "World")
{{ .Scratch.Get "hey" }} # Get
{{ .Scratch.Add "hey" "Welcome" }} # Perform addition, similar to Go language, string concatenation, numeric addition, array concatenation
{{ .Scratch.GetSortedMapValues "hey" }} # In addition to getting the map through Get, you can also return the values sorted by key
{{ .Scratch.Delete "hey" }} # Delete
{{ .Scratch.SetInMap "hey" "Hello" "World" }} # Set the map, corresponding to key:value as Hello:World
{{ .Scratch.SetInMap "hey" "Hey" "Andy" }}
{{ .Scratch.Get "hey" }} # map[Hello:World Hey:Andy]
Template Debugging
You can print the current variable information through {{ printf "%#v" .Permalink }}
. In addition, if you want to debug the page layout, you can add the following content in the <head>
for easy viewing:
<style>
div {
border: 1px solid black;
background-color: LightSkyBlue;
}
</style>
Related Articles
Hugo provides the Related Content configuration for related articles by default, and it matches the relevance by default through keywords, date, and tags.
Best Practices
The top-level directory contains archetypes
, assets
, content
, data
, i18n
, static
, layouts
several directories:
-
archetypes/: The template when creating a new article through the
new
subcommand. -
config/: By default,
hugo.[toml|yaml|json]
is used as the configuration, and the following directory method can be used:- _default/: Default configuration.
- production/: Global configuration.
- i18n/: Localization.
-
themes/:
-
halo/: The corresponding template name.
-
assets/: Resource files in the template.
- images/
-
js/: JavaScript-related scripts, see
footer/script - footer.html
for details. -
scss/: SCSS files.
-
app.scss: The top-level SCSS file, which will include files in other directories, see
head/head.html
for details.
-
app.scss: The top-level SCSS file, which will include files in other directories, see
-
static/: Static files.
-
syntax.css: The CSS file generated by the
hugo gen chromastyles
command above, seehead/head.html
for details.
-
syntax.css: The CSS file generated by the
-
layouts/: Layout templates, where
_default
is the default, andpartials
is the reference of different templates.- _default/
- blog/: Corresponding to the blog Section template.
- docs/: Corresponding to the docs Section template.
- partials/: References in different templates.
-
resume/: Corresponding to the resume Section template.
- baseof.html: The root page for rendering.
- shortcodes/: Short codes.
- slide/: Corresponding to the slide Section template.
- 404.html: Generate the 404 page.
-
assets/: Resource files in the template.
-
halo/: The corresponding template name.
The CSS-related content depends on the following files:
- syntax.css: Syntax highlighting, only needs to be compressed.
-
main.css: The core custom configuration. In order to use the bootstrap variables, it will also be referenced in the scss template. Therefore, there is no need to introduce
bootstrap.min.css
separately. - fontawesome.min.css: The used icons, and you can refer to the content in Icons.
In addition, the relevant variables of Bootstrap are saved in bootstrap/scss/_variables.scss
.
Tags
Associate articles through the default tags
and keywords
configurations. Among them, keywords
are added according to the article type, and the tags
include the following common classifications:
- topic: Special topic articles, which will sort out and display some articles centrally.
-
language: Related to programming, subdivided into specific languages such as
c/cpp
,lua
,bash
,rust
,java
,python
,golang
,web
,css
,html
, etc. -
database: Related to databases, subdivided into
mysql
, etc. -
linux: Related to the operating system, subdivided into
kvm
,network
,command
,vim
,ebpf
, etc. -
security: Related to security, subdivided into
ssh
,tls/ssl
, etc. -
container: Related content of containers, subdivided into
docker
,k8s
, etc. -
warehouse: Related content of big data, subdivided into
hudi
, etc. -
devops: Tools related to operation and development, subdivided into
git
, etc. - algorithm structure: Related to algorithm data structures.
-
example: Includes relevant example codes,
cheatsheet
for sorting out commonly used command lines, andsoftware
is more systematic than command lines.
The tag list under the title of each article can be used for jumping. At this time, it will be rendered through layouts/_default/list.html
in the template.
Leapcell: The Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis
Finally, I would like to recommend the platform that is most suitable for deploying Golang: Leapcell
1. Multi-Language Support
- Develop with JavaScript, Python, Go, or Rust.
2. Deploy unlimited projects for free
- pay only for usage — no requests, no charges.
3. Unbeatable Cost Efficiency
- Pay-as-you-go with no idle charges.
- Example: $25 supports 6.94M requests at a 60ms average response time.
4. Streamlined Developer Experience
- Intuitive UI for effortless setup.
- Fully automated CI/CD pipelines and GitOps integration.
- Real-time metrics and logging for actionable insights.
5. Effortless Scalability and High Performance
- Auto-scaling to handle high concurrency with ease.
- Zero operational overhead — just focus on building.
Explore more in the documentation!
Leapcell Twitter: https://x.com/LeapcellHQ
Top comments (0)