用 Hugo + LoveIt 搭一个初音未来主题博客:从建站到自动发布

这个博客从零到上线,大概花了一个周末。中间踩的坑不算多,但每一个都值得记下来——毕竟下次重装服务器的时候,我大概率会忘记。
这篇文章把整套流程完整写一遍:选型、建站、主题配置、首页定制、站内搜索、Nginx + HTTPS,最后一键发布。如果你也想搞一个自己的小站,可以照着抄。
一、为什么自建
用现成平台写博客当然更省事,但我想要的是:
- 完全可控:样式、域名、数据都在自己手里,不用担心平台改规则或者加广告
- 足够快:纯静态页面,Nginx 直接吐文件,没有数据库和后端
- 足够便宜:一台最低配 VPS 就够,流量也很省
- 可以折腾:对我来说,“搭博客"本身就是乐趣的一部分
所以技术选型很自然:Hugo 生成静态站 + Nginx 托管 + Let’s Encrypt 免费证书。
二、选 Hugo 和 LoveIt
Hugo 的优势是快。这个站现在只有几十个页面,构建时间 0.3 秒左右;就算以后写到几百篇,也还是秒级。
主题选了 LoveIt,理由很直白:
- 中文文档完善,配置项都有中英注释
- 自带深色模式、目录、代码复制、分享、评论等常用功能
- 默认样式干净,适合长时间阅读
- 支持本地化资源,不强制走 CDN
安装(需要 Hugo extended 版本,主题用到了 SCSS):
# 以 Ubuntu 为例,装官方 deb 包最省事
wget https://github.com/gohugoio/hugo/releases/download/v0.165.0/hugo_extended_0.165.0_linux-amd64.deb
sudo dpkg -i hugo_extended_0.165.0_linux-amd64.deb
hugo version建站和装主题:
hugo new site huxiang-blog
cd huxiang-blog
git init
git clone https://github.com/dillonzq/LoveIt themes/LoveIt三、配置里最容易出错的几个点
hugo.toml 里我改了不少,挑几个关键的:
1. baseURL 一定要带结尾斜杠
baseURL = "https://huxiang.bond/"少一个 /,站内很多绝对路径就会拼错,表现为 CSS 加载不出来或者图片 404。
2. 中文站要开 CJK
defaultContentLanguage = "zh-cn"
languageCode = "zh-CN"
hasCJKLanguage = truehasCJKLanguage 影响摘要的字数统计,不开的话中文文章的 .Summary 会短得离谱。
3. 关掉 CDN,全部本地化
LoveIt 默认会从 jsDelivr 拉字体图标、搜索库这些资源。国内访问不稳定,所以:
[params.cdn]
data = ""这样所有依赖都从主题自带的 assets/lib/ 打包进 public/,首屏不再等外网。
4. 菜单和输出格式
站内搜索需要首页额外输出 JSON:
[outputs]
home = ["HTML", "RSS", "JSON"]搜索配置:
[params.search]
enable = true
type = "lunr"
contentLength = 6000
placeholder = "搜索文章标题或内容..."中文搜索用 lunr 类型,主题会自动加载 lunr.zh.js 和 segmentit 分词库,比 Fuse.js 的字符匹配靠谱。
四、自定义首页
LoveIt 默认首页是"头像 + 文章列表”,很规整,但不够二次元。所以我用 layouts/index.html 整个覆盖了首页:
- 全屏星空 Hero,漂浮音符动画
- 一句话签名、随机文章按钮、音乐胶囊(点击播放千本桜)
- 最新文章卡片:标题、摘要、日期、阅读时长、分类全部从文章 front matter 读取
- 文章数 / 分类数 / 标签数 / 开站天数统计
- 分类 chips、标签云、最近动态时间线
关键点是不要手写卡片。我第一版是静态 HTML 写死两篇文章,结果新文章发出来首页根本不更新,非常尴尬。正确做法是遍历 site.RegularPages:
{{- $posts := where site.RegularPages "Section" "posts" -}}
{{- range first 6 $posts.ByDate.Reverse }}
<a class="card" href="{{ .RelPermalink }}">
<h3>{{ .Title }}</h3>
<p>{{ .Summary | plainify | truncate 78 }}</p>
<span>{{ .Date.Format "2006-01-02" }} · {{ .ReadingTime }} 分钟</span>
</a>
{{- end }}封面图也做了回退:优先用文章 front matter 里的 featuredImage,没有就按顺序循环用几张预设图。
五、Nginx + HTTPS
站点构建出来就是一堆静态文件,Nginx 配置很薄:
server {
server_name huxiang.bond www.huxiang.bond;
root /var/www/huxiang;
index index.html;
location ~* \.(jpg|jpeg|png|gif|webp|svg|css|js|ico)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
location / {
try_files $uri $uri/ =404;
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/huxiang.bond/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/huxiang.bond/privkey.pem;
}证书用 certbot 一条命令搞定:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d huxiang.bond -d www.huxiang.bondcertbot 会自动加 80 端口的 301 跳转,并注册 certbot.timer 定时续期,不用自己写 cron。验证一下:
systemctl list-timers | grep certbot
curl -I https://huxiang.bond/六、一条命令发布
写文章最怕流程麻烦,所以我把构建和部署包成了一个脚本 deploy.sh:
#!/usr/bin/env bash
set -e
cd "$(dirname "$0")"
HUGO_ENV=production hugo --minify --environment production
sudo rsync -a --delete public/ /var/www/huxiang/
echo "✅ 已发布: https://huxiang.bond"用法就一句:
./deploy.shrsync --delete 会同步删除线上多余文件,改标题、删文章都不会留下孤儿页面。想先本地预览就加 --preview,脚本会起 hugo server 跑在 1313 端口。
七、踩坑清单
- 首页写死卡片:新文章不显示。改成 Hugo 模板遍历。
content/about/_index.md用 section 模板:页面渲染成"所有关于我"的空归档,正文根本不出现。改成content/about/index.md这种 leaf bundle,才会走单页模板。- 文章日期格式:
date: 2026-10-30是 UTC 零点,按东八区算会显示成前一天。带时间写2026-10-30T10:00:00+08:00最稳。 - 图片路径:
/images/xxx.jpg是站根路径,不是相对当前文章。放static/images/下最省心。 hugo --minify后中文摘要被截断:检查hasCJKLanguage,以及truncate是按字符不是按词。
八、最后
整套东西的成本:一台 2 核 2G 的小 VPS,一个域名,零 CDN 费用。构建耗时 0.3 秒,首页 11KB 的 HTML,该有的功能都有。
如果你也想搭一个,建议先跑通"本地构建 + 预览",再折腾域名和证书。顺序反了容易在 DNS 和 Nginx 之间来回怀疑人生。
下一篇准备写写这台 VPS 上还跑了些什么,以及怎么用定时任务把备份、日报这些杂事自动化掉。♪