
使用Hugo+GitHub单仓库单分支快速搭建静态博客
一、github配置
1. 新建仓库
- 进入github
- 点击右上角加号New repository
- Repository name填写:你的用户名.github.io
- 点击右下角Creat repository
2. 添加个人访问令牌
- 点击右上角头像
- 点击Settings
- 点击左边栏最下方Developer settings
- Personal access tokens
- tokens (classic)
- Generate new token
- Generate new token (classic)
- note(填写名字),Expiration(选无期限No expiration),勾选权限(repo, workflow)
- 密码只会显示一次,复制保存好这个密码,待步骤4.1.3使用
二、hugo配置
0 说明
速成只需第2~4步,以dream主题 为例
1 删除站点
cd -- # 退回到用户根目录
rm -rf myblog
2 新建站点
2.1 新建站点
hugo new site myblog
2.2 下载主题
cd myblog
cd themes
git clone https://github.com/g1eny0ung/hugo-theme-dream.git dream
2.3 修改模版文件
2.3.1 路径
myblog/themes/dream/archetypes/posts.md
2.3.2 修改
post.md 文件 (line 17)draft: true,删除该行或修改为
draft: false # 关闭草稿模式
2.4. 配置主题文件
2.4.1 路径
myblog/hugo.toml
2.4.2 修改
hugo.toml 文件修改为
# 基础配置------------------------------------------------------------------------------
baseurl = "https://weihdong.github.io" # 网站根地址(必须与 GitHub Pages 地址一致)
defaultContentLanguage = "zh" # 默认内容语言
languageCode = "zh" # 网站语言代码
title = "董 玮豪(Weih Dong)" # 网站标题(显示在浏览器标签)
theme = "dream" # 使用 "dream" 主题(必须与根目录下”myblog/themes/文件名“的文件名相同)
# 第三方服务-----------------------------------------------------------------------------
[services] # 第三方服务配置区
# [services.disqus] # Disqus 评论系统
# shortname = "https-weihdong-github-io" # 需填写您的 Disqus shortname
[service.geogleAnalytics] #Geogle分析
ID = "G-Q0XX5ENN16" # 需填写跟踪 ID
# 主题参数配置----------------------------------------------------------------------------
[params]
# zenMode = true # 禅模式(极简阅读模式)
lightTheme = "emerald" # 白天主题配色方案
darkTheme = "forest" # 暗黑模式配色方案
# backgroundImage = "img/global-background.jpg" # 全局背景图路径
# backgroundImageDark = "" # 暗黑模式背景图路径
author = "Weih Dong" # 作者名称
# description = "" # 网站描述(SEO 用)
avatar = "img/head.png" # 头像图片路径
headerTitle = "Home" # 页眉显示的标题
motto = "hello world" # 副标题/座右铭
footerBottomText = "网页信息均为公开" # 页脚附加文本
collapseNavItems = ["about", "posts", "categories", "tags"] # 折叠指定导航项
stickyNav = true # 导航栏是否置顶固定
showTableOfContents = true # 显示文章目录
reorderNavItems = ["about", "search", "rss", "posts", "categories", "tags"] # 导航项排序
# noDefaultSummaryCover = true # 禁用默认摘要封面图
showSummaryCoverInPost = true # 在文章页显示摘要封面
# imageZoomableInPost = true # 允许图片点击放大
showPrevNextPost = true # 显示上一篇/下一篇导航
reorderShares = ["x", "facebook", "whatsapp", "QQ"] # 调整分享按钮顺序
# rss = true # 是否启用 RSS 订阅
# utterancesRepo = "" # GitHub 仓库名(用于 utterances 评论系统)
# valine = true # 启用 Valine 评论系统
# LEANCLOUD_APP_ID = "a9VFD9uZVBdKHIm0jqkCaoB3-MdYXbMMI" # LeanCloud 应用 ID
# LEANCLOUD_APP_KEY = "KX5hSeA31xQdbGED4T92AwFA" # LeanCloud 应用 Key
[params.valine]
enable = true # 确保启用 Valine
appId = "a9VFD9uZVBdKHIm0jqkCaoB3-MdYXbMMI" # 直接使用 appId
appKey = "KX5hSeA31xQdbGED4T92AwFA" # 直接使用 appKey
serverURLs = "https://a9vfd9uz.api.lncldglobal.com" # 国际版必须填写
placeholder = "欢迎留言"
avatar = "retro"
meta = ["nick", "mail", "link"]
# waline = true # 启用 Waline 评论系统
# walineServer = "" # Waline 服务端地址
# email = "" # 联系邮箱
siteStartYear = 2025 # 网站起始年份(用于页脚版权信息)
# favicon = "favicon.ico" # 网站图标路径
# Syntax highlighting
# customSyntaxHighlighting = true # 自定义语法高亮
#来必力配置
# livere = true #启用来必力评论系统并填写你的ID
# livereUID = "MTAyMC82MDU0MS8zNzAxMQ=="
# 布局选项------------------------------------------------------------------------------
# 高级配置------------------------------------------------------------------------------
# [params.navItems] # 自定义导航项配置区
# [params.twikoo] # Twikoo 评论系统配置
# enabled = true # 启用 Twikoo
# envID = "" # 环境 ID
# region = "" # 腾讯云区域
# lang = "" # 语言设置
# [params.advanced]
# customCSS = ["css/custom.css"] # 自定义 CSS 文件路径
# customJS = [] # 自定义 JS 文件路径
# [params.experimental] # 实验性功能
# jsDate = true # 使用 JS 渲染日期
# jsDateFormat = "yyyy年MM月dd日" # 日期显示格式
# [params.advanced]
# customCSS = ["css/custom.css"]
3. 新建文章
cd -- # 退回用户根目录确保能进入myblog目录
cd myblog
hugo new posts/first.md
新建后对应目录下打开first.md 文档以编辑文章
4. 部署远端
4.1 初始化
4.1.1 (可略过)新建忽视上传文件
- 方法一
cd --
cd myblog
echo ".DS_Store" > .gitignore
- 方法二:或通过nano方式,注:ctrl+o保存,回车确认,ctrl+x退出编辑
cd --
cd myblog
touch .gitignore
nano .gitignore
粘贴如下至 .gitignore
.DS_Store
4.1.2 建public文件
cd --
cd myblog
hugo --theme=dream --baseURL="https://weihdong.github.io/" --buildDrafts
4.1.3 初始化public文件
cd --
cd myblog
cd public
git init
git add .
git commit -m "first"
git remote add origin https://github.com/weihdong/weihdong.github.io.git
git push --set-upstream origin main #此时可能会报错‘不合法的用户名或密码',再输入一次即可,正确应输出Username for 'https://github.com':,输入你的用户名回车后粘贴个人访问令牌作为密码
4.2 大功告成,打开看看吧!
对于:https://你的用户名.github.io即你的博客页面 对于:https://github.com/你的用户名/你的用户名.github.io即你的仓库,查看code和Actions查看上传状态
5. 本地预览
cd --
cd myblog
hugo server -D
6. 自动化推送
6.1 新建deploy
cd --
cd myblog
touch deploy
nano deploy
6.2 deploy代码
通过nano方式打开后粘贴如下代码
#!/bin/bash
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
CYAN='\033[0;36m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 自动生成提交信息函数
generate_commit_msg() {
timestamp=$(date "+%Y%m%d-%H%M%S")
random_hash=$(openssl rand -hex 3)
echo "Auto-deploy:
$${timestamp}-$$
{random_hash}"
}
echo -e "\n
$${GREEN}🚀 启动部署流程...$$
{NC}"
# 生成静态网站
hugo -D || {
echo -e "\n
$${RED}❌ Hugo生成失败!$$
{NC}"
exit 1
}
cd public || exit 1
# 智能提交信息处理
if [ -z "$1" ]; then
commit_msg=$(generate_commit_msg)
echo -e "
$${YELLOW}ℹ️ 使用自动生成的提交编号:$$
{commit_msg}${NC}"
else
commit_msg="$1"
fi
# 检查是否有文件需要提交
if [ -z "$(git status --porcelain)" ]; then
echo -e "\n
$${YELLOW}⚠️ 没有需要提交的变更,跳过提交步骤$$
{NC}"
else
# 提交到GitHub
git add .
git commit -m "${commit_msg}"
git push origin main
fi
cd ..
echo -e "\n
$${GREEN}🎉 成功更新!$$
{CYAN}正在打开博客页面...${NC}"
sleep 2
open "https://weihdong.github.io"
echo -e "\n
$${CYAN}⚠️ 注意:变更可能需要1-2分钟完全生效$$
{NC}"
6.3 赋权
chmod +x deploy
6.4 运行
cd --
cd myblog
./deploy "更新博客" # 或不带请求名称./deploy
7. 关于
- 新建me.md文档
cd --
cd myblog
hugo new about/me.md
- 写入自我介绍
---
title: About Me
---
Hi, my name is Yue Yang. This is my blog.
- 在myblog/content/about/ 下新建index.md 文档
---
headless: true
---
8. 评论
8.0 说明
评论系统有来必力 、Valine 、Disqus 、Waline 等,来必力可以qq、微博等国内软件登陆,不需要梯子🪜,加载速度慢,Valine仅姓名填写即可评论,便捷,不需要梯子🪜,加载速度快,目前已停更,Waline为最新继承版本,Disqus需要梯子🪜,界面美观,仅支持x等国外社交平台登陆
8.1 来必力
- 覆盖myblog/themes/dream/layouts/_ default/single.html
{{ define "title" }}{{ .Title }}{{ end }}
{{ define "css" }}
{{ if site.Params.customSyntaxHighlighting }}
<link rel="stylesheet" data-custom-syntax-highlighting />
<style>
.chroma {
padding: 1em;
background-color: var(--dream-pre-bg, #f5f5f5);
border-radius: .5em;
overflow: auto;
}
html.dark .chroma {
background-color: var(--dream-pre-bg-dark, #262626);
}
</style>
{{ else }}
<style>
pre {
padding: 1em;
overflow: auto;
}
</style>
{{ end }}
{{ partialCached "commentSystemHeads.html" . }}
{{ end }}
{{ define "main" }}
<div class="lg:grid lg:grid-cols-4 gap-4 mt-4 px-4">
<div class="hidden lg:block">
{{ if fileExists "layouts/partials/adsense.html" }}
<div class="dream-adsense w-2/3">
{{ partialCached "adsense.html" . }}
</div>
{{ end }}
</div>
<div class="lg:col-span-2">
<article class="mx-auto prose prose-quoteless dark:prose-invert" id="dream-single-post-main" itemscope itemtype="http://schema.org/Article">
{{ template "_internal/schema.html" . }}
<header>
<h1 itemprop="headline">{{ .Title }}</h1>
<p class="text-sm">
{{ if site.Params.Experimental.jsDate }}
<span data-format="luxon">{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}</span>
{{ else }}
{{ .Date | time.Format "Monday, Jan 2, 2006" }}
{{ end }}
| <span>{{ .ReadingTime }}{{ T "minuteRead" .ReadingTime }}</span>
{{ if ne .Params.nolastmod true }}
| <span>{{ T "updatedAt" }}
{{ if site.Params.Experimental.jsDate }}
<span data-format="luxon">{{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}</span>
{{ else }}
{{ .Lastmod | time.Format "Monday, Jan 2, 2006" }}
{{ end }}</span>
{{ end }}
</p>
{{ $hasAuthor := or .Params.author site.Params.author }}
<div class="flex justify-between">
{{ if $hasAuthor }}
{{ partial "author.html" (dict "Params" .Params "template" "single") }}
{{ end }}
{{ partial "share.html" . }}
</div>
</header>
<section id="dream-single-post-content" itemprop="articleBody">
{{ if and .Params.Cover site.Params.showSummaryCoverInPost }}
<img class="w-full z-30" src="{{ .Params.Cover }}" alt="{{ .Title }}" />
{{ end }}
{{ .Content | emojify }}
{{ if fileExists "layouts/partials/adsense-post-bottom.html" }}
<div class="dream-adsense-post-bottom">
{{ partialCached "adsense-post-bottom.html" . }}
</div>
{{ end }}
</section>
{{ if site.Params.showPrevNextPost }}
<div class="divider"></div>
<div class="flex flex-col md:flex-row justify-between gap-4 py-4">
{{ with .NextInSection }}
<a role="button" class="btn btn-outline h-12" href="{{ .RelPermalink }}" title="{{ .Title }}">
<ion-icon name="chevron-back"></ion-icon>
<div class="inline-flex flex-col items-start">
<span class="text-base-content/60 text-xs font-normal">{{ T "prevPage" }}</span>
<span class="max-w-48 truncate">{{ .LinkTitle }}</span>
</div>
</a>
{{ else }}
<div></div>
{{ end }}
{{ with .PrevInSection }}
<a role="button" class="btn btn-outline h-12" href="{{ .RelPermalink }}" title="{{ .Title }}">
<div class="inline-flex flex-col items-end">
<span class="text-base-content/60 text-xs font-normal">{{ T "nextPage" }}</span>
<span class="max-w-48 truncate">{{ .LinkTitle }}</span>
</div>
<ion-icon name="chevron-forward"></ion-icon>
</a>
{{ else }}
<div></div>
{{ end }}
</div>
{{ end }}
{{ if .Site.Params.livere }}
<!-- 来必力City版安装代码 -->
<div id="lv-container" data-id="city" data-uid="MTAyMC82MDU0MS8zNzAxMQ==">
<script type="text/javascript">
(function(d, s) {
var j, e = d.getElementsByTagName(s)[0];
if (typeof LivereTower === 'function') { return; }
j = d.createElement(s);
j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
j.async = true;
e.parentNode.insertBefore(j, e);
})(document, 'script');
</script>
<noscript> 为正常使用来必力评论功能请激活JavaScript</noscript>
</div>
<!-- City版安装代码已完成 -->
{{ end }}
{{ if or site.Config.Services.Disqus.Shortname site.Params.utterancesRepo site.Params.valine site.Params.waline site.Params.twikoo.enabled }}
<div class="divider"></div>
<section class="space-y-4">
{{ partialCached "commentSystems.html" . .RelPermalink }}
</section>
{{ end }}
</article>
</div>
<div class="hidden lg:flex lg:flex-col lg:items-end">
{{ if site.Params.showTableOfContents }}
{{ .TableOfContents }}
{{ end }}
</div>
</div>
{{ end }}
{{ define "js" }}
{{ if site.Params.Experimental.jsDate }}
{{ partial "luxon.html" . }}
{{ end }}
{{ if site.Params.customSyntaxHighlighting }}
{{- $syntaxLightCSS := resources.Get "css/syntax-light.css" | minify -}}
{{- $syntaxDarkCSS := resources.Get "css/syntax-dark.css" | minify -}}
<script>
window.customSyntaxHighlighting = {
light: {{ $syntaxLightCSS.RelPermalink }},
dark: {{ $syntaxDarkCSS.RelPermalink }}
}
document.addEventListener('alpine:initialized', () => {
var isDark = Alpine.store('darkMode').isDark()
var customSyntaxHighlightingUrl = isDark ? window.customSyntaxHighlighting.dark : window.customSyntaxHighlighting.light
document
.querySelector('link[data-custom-syntax-highlighting]')
.setAttribute('href', customSyntaxHighlightingUrl)
})
</script>
{{ end }}
{{ if site.Params.imageZoomableInPost }}
{{ if fileExists "layouts/partials/medium-zoom.html" }}
{{ partialCached "medium-zoom.html" . }}
{{ else }}
<script type="module">
import mediumZoom from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';
mediumZoom('#dream-single-post-content img', {
background: 'oklch(var(--b1))',
margin: 24,
})
</script>
{{ end }}
{{ end }}
{{ end }}
- 注册来必力
- 修改myblog/homo.toml(line 77) 删除#启用代码
#来必力配置
# livere = true #启用来必力评论系统并填写你的ID
# livereUID = "MTAyMC82MDU0MS8zNzAxMQ==" #更换为自己的来必力id
8.2 Valine
- 注册Valine
- 数据化仓库新建Class:Comment
- hugo.toml(line 55) 启用并更换为你的id和key
[params.valine]
enable = true # 确保启用 Valine
appId = "a9VFD9uZVBdKHIm0jqkCaoB3-MdYXbMMI" # 直接使用 appId
appKey = "KX5hSeA31xQdbGED4T92AwFA" # 直接使用 appKey
serverURLs = "https://a9vfd9uz.api.lncldglobal.com" # 国际版必须填写
placeholder = "欢迎留言"
avatar = "retro"
meta = ["nick", "mail", "link"]
- 新增valine文件至myblog/themes/dream/layouts/partials/valine.html
<div id="vcomments"></div>
<script src="//cdn.jsdelivr.net/npm/valine@latest/dist/Valine.min.js"></script>
<script>
new Valine({
el: '#vcomments',
appId: '{{ .Site.Params.valine.appId }}',
appKey: '{{ .Site.Params.valine.appKey }}',
serverURLs: '{{ .Site.Params.valine.serverURLs }}', // 国际版必须填写
});
</script>
8.3 Waline
- 详情可参考官方文档
- 进入LeanCloud国际版
- 创建应用
- 设置-应用凭证-保存AppID、AppKey、MasterKey
- 进入vercel
- 登录并选择Github个人账户作为Git scope/仓库名自起,如waline
- 点击顶部栏设置Settings-Environment Variables分别新建3个值
- 点击Domains绑定[[域名]],使用二级域名
- 顶部栏Deployments点击最新的一次部署右侧的Redeploy重新部署
- 访问你的域名,如https://waline.085410.xyz
- 注册登录
- hugo.toml配置
waline = true # 启用 Waline 评论系统
walineServer = "https://waline.085410.xyz" # Waline 服务端地址
- myblog/themes/dream/layouts/partials/commentSystems.html 配置
{{ if site.Params.waline }}
**<article>**
{{ if fileExists "layouts/partials/waline.html" }}
{{ partialCached "waline.html" . }}
{{ else }}
**<div** id**=**"waline"**></div>**
**<script** type**=**"module"**>**
**import** { init } **from** 'https://cdn.jsdelivr.net/npm/@waline/client@3/dist/waline.js';
init({
el: '#waline',
dark: 'html.dark',
serverURL: '{{ site.Params.walineServer }}',
meta: ['nick','mail'],
lang: 'zh-CN', // 语言
emoji: [
'https://unpkg.com/@waline/[email protected]/qq',
'https://unpkg.com/@waline/[email protected]/bilibili'
//'https://unpkg.com/@waline/[email protected]/tieba'
], // 表情
//login: 'enable', // 登录方式:所有(包括匿名),disable:禁用登陆,force:必须登录
//reaction: true, // 快速反馈
//reaction: [
//'https://unpkg.com/@waline/[email protected]/tieba/tieba_agree.png',
//'https://unpkg.com/@waline/[email protected]/tieba/tieba_look_down.png'
//],
//pageview: true, // 浏览量统计
//avatar: 'monsterid', // 默认头像
requiredMeta: ['nick', 'mail'] // 必填字段
// 更多配置见官方文档: https://waline.js.org/reference/client/props.html
});
**</script>**
{{ end }}
**</article>**
{{ end }}
9. 搜索
新建空文件myblog/content/search/_index.md
10. 主题图片
图片均放在路径myblog/static/img/ 作者头像在文件中启用myblog/themes/dream/archetypes/posts.md 博客头像在文件中启用myblog/hugo.toml(line 30)
11. 网站分析
进入谷歌分析 并创建数据流,将手动生成代码粘贴至*myblog/themes/dream/layouts/paticial/head.html (line 46),复制跟踪ID至hugo.toml (line15)
12. 归档
- 新建文件
myblog/content/posts/_index.md
- 粘贴
---
groupLayout: Jan 2006
---