Hugo建站、主题修改与Cloudflare部署全流程手册


beautifulhugo主题配置、修改以及部署过程

1. 安装Hugo

1.1 macOS (推荐使用 Homebrew):

brew install hugo

1.2 Windows (推荐使用 Chocolatey 或 Scoop):

choco install hugo -confirm
# 或者下载官方 exe 文件配置环境变量

1.3 Linux:

sudo apt-get install hugo

1.4 验证安装

hugo version
# 输出示例: hugo v0.130.0 ...

2. 创建项目

2.1 创建新站点

hugo new hugo_simple

2.2 进入目录

cd hugo_simple

2.3 初始化 Git 仓库(部署必须)

git init

3. 安装Beautiful Hugo主题

3.1 使用Git Submodule方式安装,这样方便后续更新:

git submodule add https://github.com/halogenica/beautifulhugo.git themes/beautifulhugo

3.2 复制默认配置 将主题自带的示例配置复制出来作为基础:

cp themes/beautifulhugo/exampleSite/config.toml .

4. 配置修改

hugo.toml内容:

# -----------------------------------------------------------
# 基础配置 (Basic Configuration)
# -----------------------------------------------------------

# 你的网站完整域名。在本地运行(hugo server)时这里不起作用,但部署到 GitHub Pages 时必须填对
baseurl = "" 

# 网站默认语言。如果你主要写中文,建议改成 "zh-cn"
DefaultContentLanguage = "zh-cn" 
languageCode = "zh-cn"

# 网站标题,会显示在浏览器标签页和网页头部
title = "Beautiful Hugo" 

# 主题名称,必须和你 themes 文件夹下的名字完全一致
theme = "beautifulhugo" 

# 如果你是用 Hugo Module 方式安装的,取消下面这行的注释(新手一般用上面那个)
# theme = "github.com/halogenica/beautifulhugo"

# -----------------------------------------------------------
# 代码高亮设置 (Code Highlighting)
# -----------------------------------------------------------
pygmentsStyle = "trac"                 # 代码高亮的配色风格,可选值很多,如 monokai, dracula 等
pygmentsUseClasses = true              # 推荐 true,生成 CSS 类而不是内联样式,方便自定义
pygmentsCodeFences = true              # 启用 Markdown 的 ``` 代码块语法
pygmentsCodefencesGuessSyntax = true   # 自动猜测代码语言(如果你没写 ```python 这种标记)
#pygmentsUseClassic = true             # 是否使用旧版高亮引擎(一般不用开)
#pygmentOptions = "linenos=inline"     # 是否显示行号,去掉注释即可开启

# -----------------------------------------------------------
# 第三方服务 (Services) - 如果不需要可以留空
# -----------------------------------------------------------
[Services]
  [Services.Disqus]
    # Shortname = "XXX"      # 你的 Disqus 评论系统 ID,填了就会在文章下显示评论框
  [Services.googleAnalytics]
    # id = "XXX"             # 你的 Google Analytics 统计 ID (G-xxxxxx)

# -----------------------------------------------------------
# 主题特定参数 (Theme Params)
# -----------------------------------------------------------
[Params]
#  homeTitle = "Beautiful Hugo"  # 首页的大标题。如果不填,默认使用上面的 title 变量
  subtitle = "beautiful and simple website" # 副标题,显示在标题下方
  
  mainSections = ["post","posts"]      # 指定哪些文件夹里的内容算作“博客文章”
  
  logo = "img/avatar.png"         # 导航栏左上角的头像/Logo。文件需放在 static/img/ 目录下
  favicon = "img/favicon.svg"          # 浏览器标签页的小图标。文件需放在 static/img/ 目录下
  
  # 日期格式。注意:Go语言必须用 2006-01-02 代表 YYYY-MM-DD,不能乱改数字
  dateFormat = "January 2, 2006"       
  
  commit = false                       # 是否在文章底部显示 Git 提交信息(一般不开)
  rss = true                           # 是否生成 RSS 订阅源
  comments = true                      # 是否全局开启评论功能
  readingTime = true                   # 是否显示“阅读需 X 分钟”
  wordCount = true                     # 是否显示文章字数
  useHLJS = true                       # 是否使用 highlight.js (前端高亮库),建议开启
  socialShare = true                   # 是否在文章底部显示分享按钮(Twitter, FB等)
  delayDisqus = true                   # 延迟加载 Disqus 评论,能加快网页打开速度
  showRelatedPosts = true              # 是否在文章底部显示“相关文章”推荐
  
#  cusdisID = "XXX"                    # 另一种评论系统 Cusdis 的 ID
#  hideAuthor = true                   # 是否隐藏作者名字
#  gcse = "0123..."                    # Google 自定义搜索 ID,填了会把搜索框变成 Google 搜索
#  disclaimerText = "..."              # 页脚的免责声明文字

# -----------------------------------------------------------
# 首页大图轮播 (Big Image / Hero Image)
# -----------------------------------------------------------
# 下面这些是首页顶部的大图设置。如果不想要大图,就把这几行都删掉或者注释掉

#[[Params.bigimg]]
#  src = "img/triangle.jpg"  # 图片路径 (static/img/...)
#  desc = "Triangle"         # 图片描述
#[[Params.bigimg]]
#  src = "img/sphere.jpg"
#  desc = "Sphere"
#  position = "center top"   # CSS 定位参数
#[[Params.bigimg]]
#  src = "img/hexagon.jpg"
#  desc = "Hexagon"

# -----------------------------------------------------------
# 作者社交链接 (Author Social Links)
# -----------------------------------------------------------
[Params.author]
  name = "xxsky"       # 你的名字(用于页脚版权声明)
  website = "https://nav.hxjx.hidns.co" # 你的个人主页链接
  email = "xuhxjxhk@gmail.com" # 你的邮箱,填了会在页脚显示邮箱图标
  
  # 下面这些社交账号,有哪个填哪个,没有的直接留空或删除即可,图标会自动显示
  facebook = "username"
  github = "username"        # 比如填 halogenica,不要填完整 URL
  # gitlab = "username"
  # bitbucket = "username"
  # twitter = "username"
  # reddit = "username"
  # linkedin = "username"
  # stackoverflow = "users/XXXXXXX/username"
  # instagram = "username"
  # youtube = "user/username" 
  # weibo = "username"       # 微博
  # zhihu = "username"       # 知乎 (部分版本支持)

# -----------------------------------------------------------
# 菜单栏设置 (Menu)
# -----------------------------------------------------------

# 1. 普通菜单链接
[[menu.main]]
    name = "Blog"            # 菜单显示的文字
    url = ""                 # 点击跳转的链接,"" 代表首页
    weight = 1               # 排序权重,数字越小越靠左

[[menu.main]]
    name = "About"
    url = "page/about/"      # 对应 content/page/about.md
    weight = 3

# 2. 下拉菜单示例 (父级)
[[menu.main]]
    identifier = "samples"   # 唯一标识符,用于被子菜单引用
    name = "Samples"         # 显示文字
    weight = 2

# 2.1 下拉菜单 (子级)
[[menu.main]]
    parent = "samples"       # 必须填上面的 identifier
    name = "Big Image Sample"
    url = "post/2017-03-07-bigimg-sample"
    weight = 1

[[menu.main]]
    parent = "samples"
    name = "Math Sample"
    url = "post/2017-03-05-math-sample"
    weight = 2

[[menu.main]]
    parent = "samples"
    name = "Code Sample"
    url = "post/2016-03-08-code-sample"
    weight = 3

# 3. 标签云页面链接
[[menu.main]]
    name = "Tags"
    url = "tags"
    weight = 3

5. 主题模板核心修复 (代码修改)

5.1 修复post_preview.html(防止内容泄露) 解决 “首页错误显示第一篇文章完整内容” 的 Bug

文件位置: themes/beautifulhugo/layouts/partials/post_preview.html

操作: 找到 post-entry 部分,将错误的 .Content 替换为 .Summary。 修改后的代码片段:

<div class="post-entry">
    {{ if or (.Truncated) (.Params.summary) }}
        {{ .Summary }}
        <a href="{{ .Permalink }}" class="post-read-more">[{{ i18n "readMore" }}]</a>
    {{ else }}
        {{ .Summary }}  {{ end }}
</div>

5.2. 修复 index.html (首页安全过滤)

  • 文件位置: layouts/index.html (如果没有,请从 themes/beautifulhugo/layouts/index.html 复制一份到项目根目录的 layouts 文件夹)

  • 操作: 在循环中增加 .IsHome 判断

修改后的代码片段:

<div class="posts-list">
  {{ $pag := .Paginate (where site.RegularPages "Type" "in" site.Params.mainSections) }}
  {{ range $pag.Pages }}
    {{/* 确保跳过被错误识别为页面的首页索引 */}}
    {{ if not .IsHome }}
      {{ partial "post_preview" . }}
    {{ end }}
  {{ end }}
</div>

5.3 自定义页脚版权 (可选)

  • 文件位置: themes/beautifulhugo/layouts/partials/footer.html

  • 操作: 搜索 copyright 修改版权文字,搜索 poweredBy 删除或修改“由 Hugo 驱动”的字样

5.4 修改版权与驱动信息 目的: 去掉 “Powered by Hugo” 和 “Theme by Beautiful Hugo”。 操作: 复制主题文件到 layouts/partials/footer.html,然后修改:

<p class="credits theme-by text-muted">
  {{ i18n "poweredBy" . | safeHTML }}
  {{ if $.GitInfo }}...{{ end }}
</p>

<p class="credits theme-by text-muted">
  Copyright &copy; {{ now.Format "2006" }} {{ .Site.Params.author.name }}
</p>

也可以直接删掉p段

5.5 修改文章元信息 目的: 文章标题下不显示“By [作者名]”,只显示日期。 操作: 复制主题文件到 layouts/partials/post_meta.html,然后修改:

{{ if .Params.author }}
  {{ i18n "postedBy" }} <span class="post-meta-user">{{ .Params.author }}</span>
{{ end }}

5.6 网站头像 位置:layouts/partials/nav.html 去掉头像圆圈,替换成下面字段

<a class="navbar-brand" href="{{ "" | absLangURL }}">{{ .Site.Title }}</a>

或强制指向首页

<a class="navbar-brand" href="/">

5.7 日期显示 位置:layouts/partials/post_meta.html

  {{ $lastmodstr := .Lastmod | time.Format ":2006-1-2" }}
  {{ $datestr := .Date | time.Format ":2006-1-2" }}

或文章标题下不显示作者名字,删除作者判断逻辑

{{ if .Params.author }}
  {{ i18n "postedBy" }} <span class="post-meta-user">{{ .Params.author }}</span>
{{ end }}

5.7 加载动画、深浅模式、样式更改 位置:layouts\partials\head_custom.html

<style>
/* ======================================================= */
/* 1. 基础重置 */
/* ======================================================= */
html, body { height: 100%; margin: 0; padding: 0; }
body { transition: background-color 0.3s ease, color 0.3s ease; }

/* ======================================================= */
/* 2. 深色模式 (Dark Mode) - 基础配色 */
/* ======================================================= */
body.dark-mode {
    background-color: #1e1e1e !important;
    color: #e6e6e6 !important;
}

/* 链接颜色 (仅正文生效) */
body.dark-mode a { color: #4daafc; }

/* 标题与文字 */
body.dark-mode h1, body.dark-mode h2, body.dark-mode h3, 
body.dark-mode h4, body.dark-mode h5, body.dark-mode h6,
body.dark-mode .post-title, body.dark-mode .post-heading h1 { color: #fff !important; }
body.dark-mode .post-meta { color: #858585 !important; }

/* 首页分割线 & 底部线条 */
body.dark-mode .post-preview { border-bottom: 1px solid #333 !important; }
body.dark-mode hr { border-color: #333 !important; opacity: 0.6; }

/* 页脚 */
body.dark-mode footer { background: #1e1e1e !important; color: #777 !important; border-top-color: #333 !important; }

/* ======================================================= */
/* 3. 导航栏 (菜单栏) 优化 */
/* ======================================================= */

/* 背景:深灰 */
body.dark-mode .navbar-custom {
    background-color: #252526 !important; 
    border-bottom: 1px solid #333 !important;
}

/* 字体颜色:提亮到 #e0e0e0 (亮灰白) */
body.dark-mode .navbar-custom .navbar-brand,
body.dark-mode .navbar-custom .nav > li > a {
    color: #e0e0e0 !important; 
}

/* 鼠标悬停:变纯白 */
body.dark-mode .navbar-custom .navbar-brand:hover,
body.dark-mode .navbar-custom .nav > li > a:hover {
    color: #ffffff !important;
}

/* ======================================================= */
/* 4. 切换按钮 (半黑半白圆圈版) */
/* ======================================================= */
.theme-toggle-btn {
    display: flex; align-items: center; justify-content: center; height: 100%; padding: 15px; 
    cursor: pointer; 
    color: #555; /* 浅色模式下的圆圈颜色 */
    transition: color 0.3s, transform 0.3s; /* 加入旋转动画过渡 */
    font-size: 22px; /* 圆圈稍微大一点更好看 */
    line-height: 1;
}
.theme-toggle-btn:hover { color: #000; }
body.dark-mode .theme-toggle-btn { color: #ddd; } /* 深色模式下的圆圈颜色 */
body.dark-mode .theme-toggle-btn:hover { color: #fff; }

/* ======================================================= */
/* 5. 滚动条美化 */
/* ======================================================= */
body.dark-mode ::-webkit-scrollbar { height: 10px; width: 10px; background: #1e1e1e; }
body.dark-mode ::-webkit-scrollbar-thumb { background: #444; border-radius: 5px; }
body.dark-mode ::-webkit-scrollbar-thumb:hover { background: #555; }
body.dark-mode ::-webkit-scrollbar-corner { background: #1e1e1e; }

/* ======================================================= */
/* 6. 代码块逻辑 (完美版:去框 + 红悬停 + 智能折叠) */
/* ======================================================= */
.highlight button:not(.c-btn), .copy-to-clipboard, .copy-code-button { display: none !important; }
.highlight { position: relative !important; }

/* C. 深色模式 - 无边框融合 */
body.dark-mode .highlight {
    background-color: #1e1e1e !important;
    border: 1px solid #333 !important; 
    border-radius: 6px !important;
}
body.dark-mode .highlight pre, body.dark-mode .highlight code,
body.dark-mode .highlight table, body.dark-mode .highlight tr, body.dark-mode .highlight td {
    background-color: transparent !important; color: #d4d4d4 !important; border: none !important;
}

/* 语法高亮 */
body.dark-mode .chroma .k, body.dark-mode .chroma .kd, body.dark-mode .chroma .kt { color: #569cd6 !important; } 
body.dark-mode .chroma .s, body.dark-mode .chroma .s1 { color: #ce9178 !important; } 
body.dark-mode .chroma .c, body.dark-mode .chroma .c1 { color: #6a9955 !important; } 
body.dark-mode .chroma .nf { color: #dcdcaa !important; } 
body.dark-mode .chroma .lnt { color: #555 !important; }

/* D. 按钮组 */
.code-tools { 
    position: absolute; top: 4px; right: 4px; z-index: 20; display: flex;
    background: transparent !important; opacity: 0; transition: opacity 0.2s;
}
.highlight:hover .code-tools { opacity: 1; }

/* 按钮样式 */
.c-btn { 
    width: 26px; height: 26px; 
    border: none !important; background: transparent !important; 
    cursor: pointer; padding: 0; margin: 0;
    display:flex; justify-content:center; align-items:center; 
    transition: color 0.2s ease;
    color: #999; 
}
.c-btn:hover { color: #ff4757 !important; }
body.dark-mode .c-btn { color: #666; }
body.dark-mode .c-btn:hover { color: #ff4757 !important; }

/* E. 折叠 */
.highlight.folded { height: 200px !important; overflow: hidden !important; }

/* ======================================================= */
/* 7. Halo 赛车动画 */
/* ======================================================= */
#halo-racer-loader { 
    position: fixed !important; top: 0 !important; left: 0 !important; right: 0 !important; bottom: 0 !important;      
    width: 100% !important; height: 100% !important; z-index: 999999999 !important; 
    background: #ffffff; display: flex !important; justify-content: center !important; align-items: center !important; 
    transition: opacity 0.3s ease, visibility 0.3s ease;
}
body.dark-mode #halo-racer-loader { background: #1e1e1e !important; }
#halo-racer-loader.hidden { opacity: 0; visibility: hidden; }

.racer-container { position: relative; width: 80px; height: 20px; }
.bar { position: absolute; top: 0; left: 0; width: 12px; height: 20px; border-radius: 0; }
.p1 { background: rgba(255,71,87,0.2); z-index:1; animation: run 1.5s cubic-bezier(.4,0,.2,1) infinite 0.15s; }
.p2 { background: rgba(255,71,87,0.5); z-index:2; animation: run 1.5s cubic-bezier(.4,0,.2,1) infinite 0.08s; }
.red { background: #ff4757; z-index:10; animation: run 1.5s cubic-bezier(.4,0,.2,1) infinite 0s; }
@keyframes run { 0%{left:0} 30%{left:68px} 50%{left:68px} 80%{left:0} 100%{left:0} }

/* ======================================================= */
/* 8. 去除手机端菜单框 & 上下篇边框 */
/* ======================================================= */
/* A. 手机端导航栏按钮 (三横杠) 去框 */
.navbar-toggle { border: none !important; background: transparent !important; }
.navbar-toggle:hover, .navbar-toggle:focus { background: transparent !important; }
.navbar-default .navbar-toggle .icon-bar { background-color: #888 !important; }
body.dark-mode .navbar-toggle .icon-bar { background-color: #e0e0e0 !important; }

/* B. 上一篇/下一篇 (Pager) 去框 */
.pager li > a, .pager li > span {
    border: none !important; background-color: transparent !important; 
    padding: 10px 0 !important; font-weight: bold;                  
}
body.dark-mode .pager li > a, body.dark-mode .pager li > span {
    background: transparent !important; border: none !important; color: #ccc !important;
}
.pager li > a:hover, .pager li > a:focus {
    background-color: transparent !important; color: #0085a1 !important; 
}
body.dark-mode .pager li > a:hover { color: #fff !important; }
</style>

<script>
// 1. 注入动画
(function() {
  document.write(`<div id="halo-racer-loader"><div class="racer-container"><div class="bar p1"></div><div class="bar p2"></div><div class="bar red"></div></div></div>`);
  window.addEventListener('load', function() {
    const loader = document.getElementById('halo-racer-loader');
    setTimeout(() => { if(loader){ loader.classList.add('hidden'); setTimeout(() => { loader.style.display = 'none'; }, 300); }}, 800); 
  });
})();

// 2. 深色模式切换 (修复:使用半黑半白圆圈)
(function() {
    const isDark = localStorage.getItem('theme') === 'dark';
    if(isDark) document.body.classList.add('dark-mode');

    document.addEventListener('DOMContentLoaded', function() {
        const navList = document.querySelector('.navbar-nav'); 
        if(!navList) return;

        const li = document.createElement('li');
        const link = document.createElement('a');
        link.className = "theme-toggle-btn";
        link.title = "Switch Theme";
        
        // 【核心修改】使用 Unicode 几何图形
        // ◑ (右黑) / ◐ (左黑) 
        link.innerHTML = isDark ? "◑" : "◐"; 
        
        link.onclick = function() {
            document.body.classList.toggle('dark-mode');
            const currentMode = document.body.classList.contains('dark-mode') ? 'dark' : 'light';
            localStorage.setItem('theme', currentMode);
            
            // 点击切换时的图标翻转逻辑
            link.innerHTML = currentMode === 'dark' ? "◑" : "◐";
        };
        li.appendChild(link);
        navList.appendChild(li);
    });
})();

// 3. 代码块工具
document.addEventListener('DOMContentLoaded', function() {
    const svgCopy = '<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>';
    const svgCheck = '<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="#28a745" stroke-width="3"><polyline points="20 6 9 17 4 12"></polyline></svg>';
    const svgFold = '<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 15 12 9 6 15"></polyline></svg>';
    const svgUnfold = '<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"></polyline></svg>';

    document.querySelectorAll('.highlight').forEach(block => {
        if (block.querySelector('.code-tools')) return;
        
        const tools = document.createElement('div');
        tools.className = 'code-tools';

        let isLongCode = block.offsetHeight > 300;
        if (isLongCode) {
            const btnFold = document.createElement('button'); 
            btnFold.className = 'c-btn';
            
            block.classList.add('folded'); 
            btnFold.innerHTML = svgUnfold; 
            btnFold.title = "展开"; 
            
            btnFold.onclick = () => { 
                if (block.classList.contains('folded')) {
                    block.classList.remove('folded');
                    btnFold.innerHTML = svgFold; 
                    btnFold.title = "折叠";
                } else {
                    block.classList.add('folded');
                    btnFold.innerHTML = svgUnfold; 
                    btnFold.title = "展开";
                    block.scrollIntoView({behavior: "smooth", block: "center"});
                }
            };
            tools.appendChild(btnFold);
        }

        const btnCopy = document.createElement('button'); 
        btnCopy.className = 'c-btn'; 
        btnCopy.innerHTML = svgCopy; 
        btnCopy.title = "复制";
        
        btnCopy.onclick = () => {
            navigator.clipboard.writeText(block.innerText).then(() => {
                btnCopy.innerHTML = svgCheck;
                setTimeout(() => { btnCopy.innerHTML = svgCopy; }, 2000);
            });
        };
        
        tools.appendChild(btnCopy); 
        block.appendChild(tools);
    });
});
</script>

5.8 汉化修正 位置:themes\beautifulhugo\i18n\zh-CN.yaml

6. 创建内容与本地测试

6.1 创建文章

hugo new posts/hello-world.md

6.2 本地预览

hugo server

访问 http://localhost:1313,确保首页显示正常(只有标题和摘要,没有全文)

7. 推送到 GitHub 并部署 Cloudflare Pages

7.1 提交代码到 GitHub 在项目根目录下:

# 1. 创建 .gitignore 文件(如果没有)
echo "public" >> .gitignore
echo "resources" >> .gitignore

# 2. 提交所有更改
git add .
git commit -m "完成站点配置与Bug修复"

# 3. 推送到远程仓库 (假设您已在 GitHub 创建了仓库)
git branch -M main
git remote add origin https://github.com/您的用户名/您的仓库名.git
git push -u origin main

此方法是在登陆github帐号的情况下切换仓库 如果推送出现网络故障可以开启代理,以v2rayN的端口为例。

git config --global http.proxy http://127.0.0.1:10808
git config --global https.proxy http://127.0.0.1:10808

7.2 Cloudflare Pages 部署设置

  • 登录 Cloudflare Dash: 进入 Workers & Pages -> Create Application -> Connect to Git。

  • 选择仓库: 选中刚才推送的 my-blog 仓库。

  • 构建配置 (Build Settings):

    • Framework preset: 选择 Hugo。

    • Build command: 保持 hugo。

    • Build output directory: 保持 public。

  • 开始部署: 点击 Save and Deploy。

8. 后续维护

  • 更新文章: 在本地 hugo new post/xxx.md,写完后 git add . -> git commit -> git push,Cloudflare 会自动触发更新。

  • 排错: 如果部署后样式错乱或不更新,去 Cloudflare 页面点击 Purge Cache (清除缓存)。

  • 推送源码

git add .
git commit -m "new blog"
git push

也可以看看