Featured image of post Hugo主题hugo-theme-stack部署记录

Hugo主题hugo-theme-stack部署记录

Hugo主题hugo-theme-stack部署记录

起因

冲浪过程中搜索Linux命令行使用mihomo内核的方法,结果发现一个宝藏博主:亂筆,观看多篇博文发现是一个技术与想法并存的有趣的人,收藏关注点赞三连之后发现博客主题不错,遂在页脚寻找主题信息,发现是使用Hugostack主题,没听过,去查了一下,这是它们各自官方的介绍:

Hugo is a static site generator written in Go, optimized for speed and designed for flexibility.

Hugo Theme Stack: Card-style Hugo theme designed for bloggers.

明白了,Go语言写的博客主题,看着不错,凭借去年折腾Halo主题的经验,想整一个这种纯静态的博客试试。先说一下对于一个已经有多个博客的人想折腾hugo主题的动机。

动机

  1. 我还没玩过静态blog
  2. 现在有很多SAAS公司提供静态网站托管,简言之就是可以白嫖
  3. 体验一下运维式的blog撰写过程
  4. 亂筆的高质量内容搭配这个主题让我很心动

开始

找到了这个主题的作者CaiJimmy,使用其推荐的Quick Start项目hugo-theme-stack-starter,但是部署完之后发现可能应该使用主主仓库的,这是后话,有时间再折腾主仓库的事。

  1. 点击右上方的Use this template按钮,下拉列表中使用Create a new repository use_this_temlate
  2. 创建一个新仓库页面,输入Repository name,描述可写可不写,因为这个starter项目要把博文直接保存在仓库中,Choose visbility我选择了Private new_git_repo
  3. 创建codespace。在仓库中找到我们刚才已经fork的项目,右上方位置,绿色的Code按钮,下拉菜单中选择创建codespace,稍作等待,会在新标签页中出来在线版本的vscode IDE create_codespace
  4. 在线版本的vs code长这样,和桌面版本也不差多少了。 codespace_main
  5. 在中间下方的TERMINAL中输入hugo server进入预览界面,跑通之后点击Open in browser会在新标签页打开blog hugo_server

Cloudflare部署

  1. 进入cloudflareWorkers & PagesCreate applicationPagesImport an existing Git repositoryGet started cloudflare_create_application
  2. 绑定github账号,如果没有就根据提示绑定刚才folk仓库的账号,然后选择对应仓库,如果没有发现仓库,请那就是没有允许cloudflare完全访问github账号,比如我,点击正文的连接进入github设置中将对应仓库的访问权限给cloudflare cloudflare_select_repository
  3. 下一步,Set up builds and deployments中,有几个注意点,Framework presetNone,也可以选Hugo,没影响,Build command留空,Build output directory只输入.,点开Environment variables (advanced)加入两个参数,GO_VERSIONHUGO_VERSION,对应参数值分别为1.110.93.2,完工,Save and Deploy cloudflare_set_up_builds
  4. 等待Deploy site完成,出现Success表示部署成功。 cloudflare_deploy_site

写博客

很好,现在可以开始写博客了。 让我们回到在线vscode这边,在文件目录中创建一个文件命名为:archetypespost.md,在其中加入如下内容

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
---
title: "{{ replace .Name "-" " " | title }}"
description: ""
date: {{ .Date }}
draft: false

categories:
  - "xxxx"
tags:
  - "tag1"
  - "tag2"

toc: true

cover:
  image: ""
  alt: ""
  caption: ""

author:
  name: ""
---

这一步的目的是为了定制每次使用代码生成.md文档的front-matter也就是对应博文的属性。 现在就可以正式开始写博客了。 在TERMINAL中输入hugo new post/xxx/index.md创建新文件,可以看到已经自动生成了我们设置好的front-matter,在front-matter之后撰写博文。 codespace_new_post 写完之后的流程如下:

1
2
3
git add .
git commit -m "xxxxx"
git push

因为作者已经在安排了自动化操作,我们不需要再执行其他操作,Github Action会自动编排将内容编排成静态网页,并且cloudflare也会自动部署新的一笔提交。

整合Artalk评论服务

我看一个博主说评论是一个博客的重要组成部分,我也认为评论是一个博客的活力来源的一部分。所以应该有评论服务。CaiJimmy这个项目默认使用Disqus这个东西,我也试着去注册了一下,但是直接看到用户协议里说了可以使用和出售用户信息,免费计划还有广告,我就吐了。想着换一个,正好亂筆目标博客使用的是Artalk,那我也效仿一下了。 首先,artalk是一个服务,查了一下是要部署在服务器的,而且因为要持久化评论内容还有数据库,那么,cloudflare应该是不能白嫖了,还有其他方法吗?有的,查了一下还有一个SAAS商家他们家可以在免费额度内白嫖,但是需要绑定信用卡防止滥用,它就是fly.io,付款方式我的选择的Google Play,经过测试bybit的虚拟信用卡是不可以的。

  1. 安装官方的CLI工具,我是windows还挺方便的
1
2
# 使用Powershell终端执行就好了
pwsh -Command "iwr https://fly.io/install.ps1 -useb | iex"
  1. 登录
1
fly auth login

按照提示登录 3. 创建项目目录并发起launch

1
2
3
4
5
# 创建并进入项目文件夹
mkdir my-artalk-server
cd my-artalk-server
# 启动程序,只生成配置文件但是不部署
fly launch --no-deploy

launch这一步会问要不要修改配置Do you want to tweak these settings before proceeding?,当然了,我们选y,之后会打开网页,让我们完成配置,非常的nice,选择最小号的x1型号的cpu和256m内存就行,毕竟是用免费的额度。完成配置之后文件夹中出现.toml格式的文件。

  1. 创建持久化存储卷,我选择的是nrt也就是Japanese Tokyo
1
fly volumes create artalk_data --size 1 --region <你选择的区域> --app <你刚才起的名字>
  1. 修改配置文件并部署
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#根据自动生成的FLY.TOML文件修改
app = "artalk"  
primary_region = "nrt"

[build]
  image = "artalk/artalk-go"

[http_service]
  internal_port = 23366
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 0
  processes = ["app"]

[[mounts]]
  source = "artalk_data"
  destination = "/data"
  1. 创建管理员账号与添加Trusted Domainfly项目文件夹中,也就是和toml文件一个目录下使用终端执行
1
2
3
4
5
6
7
# 进入容器内
flyctl ssh console
# 创建管理员账号
./artalk admin
# 按照提示创建管理员账号
# 重启服务
flctl apps restart

通过fly.io网页进入artalk后台,域名通常是https://app-name.fly.dev,使用上一步创建的管理员账号登录。添加站点,其中Site Name要记住,Site URLs就是cloudflare中访问hugo的网址。 artalk_site 并在设置中添加vs code的预览地址和实际访问地址到信任域名中: artalk_setting

  1. 整合进stack主题 创建layouts_defaultsingle.html并写入
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{{ define "body-class" }}
    article-page
    {{/* 
        Enable the right sidebar if
            - Widget different from 'TOC' is enabled
            - TOC is enabled and not empty
    */}}
    {{- $HasWidgetNotTOC := false -}}
    {{- $TOCWidgetEnabled := false -}}
    {{- range .Site.Params.widgets.page -}}
        {{- if ne .type "toc" -}}
            {{ $HasWidgetNotTOC = true -}}
        {{- else -}}
            {{ $TOCWidgetEnabled = true -}}
        {{- end -}}
    {{- end -}}

    {{- $TOCManuallyDisabled := eq .Params.toc false -}}
    {{- $TOCEnabled := and (not $TOCManuallyDisabled) $TOCWidgetEnabled -}}
    {{- $hasTOC := ge (len .TableOfContents) 100 -}}
    {{- .Scratch.Set "TOCEnabled" (and $TOCEnabled $hasTOC) -}}
    
    {{- .Scratch.Set "hasWidget" (or $HasWidgetNotTOC (and $TOCEnabled $hasTOC)) -}}
{{ end }}

{{ define "main" }}
    {{ partial "article/article.html" . }}

    {{ if .Params.links }}
        {{ partial "article/components/links" . }}
    {{ end }}

    {{ partial "article/components/related-content" . }}
     
    {{ if not (eq .Params.comments false) }}
        {{ partial "comments/include" . }}
    {{ end }}

    {{ partialCached "footer/footer" . }}

    {{ partialCached "article/components/photoswipe" . }}
{{ end }}

{{ define "right-sidebar" }}
    {{ if .Scratch.Get "hasWidget" }}{{ partial "sidebar/right.html" (dict "Context" . "Scope" "page") }}{{ end}}
{{ end }}

创建layoutspartialscommentsproviderartalk.html并写入

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<link href="{{ $.Site.Params.comments.artalk.server }}/dist/Artalk.css" rel="stylesheet">
<script src="{{ $.Site.Params.comments.artalk.server }}/dist/Artalk.js"></script>
<div id="Comments"></div>

<script>
    const artalk = Artalk.init({
        el: '#Comments',
        pageKey: '{{ .Permalink }}',
        pageTitle: '{{ .Title }}',
        server: '{{ $.Site.Params.comments.artalk.server }}',
        site: '{{ $.Site.Title }}',
        locale: "auto"
    })
    window.addEventListener('onColorSchemeChange', (e) => {
        if (e.detail === 'dark') {
            artalk.setDarkMode(true)
        } else {
            artalk.setDarkMode(false)
        }
    })
</script>

修改config_defaultparams.toml文件

1
2
3
4
5
6
7
8
9
## Comments
[comments]
enabled = true
provider = "artalk"

[comments.artalk]
server = "your-server-domains/ip"
site = "your-site-name" #要与第6步中的Site Name对应
nest = true

如果评论部分出现错误:Artalk Error应该是没把对应的域名加入Trusted Domain中。

实际效果展示 hugo-site

2025.11.13更新

之前设置的front-matter有点小问题,在我设置封面图的时候发现不管用,遂去翻了一下stack官方文档hugo官方文档,重新贴一下更新后的模板。位置还是照旧:archetypespost.md

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
---
# 文章标题 — 必填,Hugo 会用 .Title 方法访问
title: "{{ replace .Name "-" " " | title }}"

# 创建/发布日期 — 建议自动使用 .Date 模板变量
date: {{ .Date }}

# 最后修改日期 — 如果文章更新时手动修改,否则可与 date 相同或留空
lastmod: {{ .Date }}

# 真正发布时间(如果与 date 不同) — Hugo 的 PublishDate 方法访问。:contentReference[oaicite:3]{index=3}
publishDate: {{ .Date }}

# 到期/取消发布日期 — 如果文章在某日期后不再发布,可填;默认为空
expiryDate: ""

# 自定义链接尾部 slug — 覆盖默认 URL 的最后一段(Hugo 的 slug 方法使用):contentReference[oaicite:4]{index=4}
slug: ""

# 分类(categories) — 文章所属分类,使用数组格式
categories: []

# 标签(tags) — 文章标签,用于文章归类、检索
tags: []

# 描述/摘要 — 通常用于 meta 标签 description。:contentReference[oaicite:5]{index=5}
description: ""

# 预览或封面图片 — 主题特有字段(Stack 主题),也可用于 OpenGraph、Twitter 等
image: ""

# 是否开启评论 — 主题特有字段(Stack 主题)
comments: true

# 授权信息 — 主题特有字段
license: ""

# 是否启用数学公式(KaTeX) — 主题特有字段
math: false

# 是否显示目录(Table of Contents) — 主题特有字段
toc: true

# 是否显示阅读时间 — 主题特有字段
readingTime: true

# SEO 关键词 — Hugo 自身支持 keywords 字段。:contentReference[oaicite:6]{index=6}
keywords: []

# (可选)样式字段 — 主题特有,用于如 badge 背景色等
style: ""

# (推荐)是否草稿状态 — Hugo 的 draft 字段。若为 true 则不会发布,除非使用 --buildDrafts。:contentReference[oaicite:7]{index=7}
draft: true

# (推荐)文章是否置顶/特色 — 主题可能支持 featured 字段,可按需添加:
# featured: false

---

无注释版

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
lastmod: {{ .Date }}
publishDate: {{ .Date }}
slug: ""
categories: []
tags: []
description: ""
image: ""
comments: true
license: ""
math: false
toc: true
readingTime: true
keywords: []
---