<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>PaperMod on 北海</title>
    <link>https://blog-6sm.pages.dev/tags/papermod/</link>
    <description>Recent content in PaperMod on 北海</description>
    <image>
      <title>北海</title>
      <url>https://blog-6sm.pages.dev/images/og-default.png</url>
      <link>https://blog-6sm.pages.dev/images/og-default.png</link>
    </image>
    <generator>Hugo</generator>
    <language>zh</language>
    <copyright>2026</copyright>
    <lastBuildDate>Wed, 08 Apr 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://blog-6sm.pages.dev/tags/papermod/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>你好，世界</title>
      <link>https://blog-6sm.pages.dev/posts/hello-world/</link>
      <pubDate>Wed, 08 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://blog-6sm.pages.dev/posts/hello-world/</guid>
      <description>这是我的第一篇博客文章，介绍本博客的内容方向和技术架构。</description>
      <content:encoded><![CDATA[<h2 id="欢迎">欢迎</h2>
<p>欢迎来到我的博客！这里将分享关于 AI、大语言模型和软件工程的技术文章。</p>
<h2 id="内容方向">内容方向</h2>
<p>本博客计划涵盖以下领域：</p>
<ul>
<li><strong>技术深度文章</strong>：深入分析 AI/LLM 领域的关键技术</li>
<li><strong>行业观察</strong>：追踪 AI 领域的最新动态和趋势</li>
<li><strong>工程实践</strong>：分享软件工程中的经验和最佳实践</li>
</ul>
<h2 id="技术栈">技术栈</h2>
<p>本博客使用以下技术搭建：</p>
<ul>
<li><a href="https://gohugo.io/">Hugo</a> — 高性能静态网站生成器</li>
<li><a href="https://github.com/adityatelange/hugo-PaperMod">PaperMod</a> — 简洁优雅的 Hugo 主题</li>
<li><a href="https://pages.cloudflare.com/">Cloudflare Pages</a> — 全球 CDN 部署</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="c1"># 一段示例代码</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">hello</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Hello, World!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">hello</span><span class="p">()</span>
</span></span></code></pre></div><h2 id="下一步">下一步</h2>
<p>敬请期待更多内容！</p>
]]></content:encoded>
    </item>
    <item>
      <title>用 Hugo &#43; Cloudflare Pages 搭了个博客</title>
      <link>https://blog-6sm.pages.dev/posts/build-blog-with-hugo/</link>
      <pubDate>Wed, 08 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://blog-6sm.pages.dev/posts/build-blog-with-hugo/</guid>
      <description>记录用 Hugo、PaperMod 主题和 Cloudflare Pages 从零搭建双语技术博客的完整过程，包括踩过的坑和做过的技术选型。</description>
      <content:encoded><![CDATA[<p>一直想搭个博客，但一直在&quot;想&quot;的阶段。直到最近觉得再不动手就永远不会动手了，花了一个下午把整个站点从零搭到上线。这篇文章把过程记录下来，不是教程——网上 Hugo 教程已经够多了——更像是一份带注释的踩坑日志。</p>
<h2 id="为什么是-hugo">为什么是 Hugo</h2>
<p>选静态站点生成器这件事，我其实没纠结太久。之前用过 Hexo，知道 Node.js 生态的依赖地狱是什么体验。Jekyll 太慢，Gatsby 太重。Hugo 是 Go 写的单二进制文件，<code>brew install hugo</code> 之后就能用，没有 <code>node_modules</code>，没有依赖冲突，构建速度快到几乎感觉不到在构建。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew install hugo
</span></span><span class="line"><span class="cl">hugo version
</span></span><span class="line"><span class="cl"><span class="c1"># hugo v0.160.0+extended darwin/arm64</span>
</span></span></code></pre></div><p>跑完这两行就算装好了。<code>extended</code> 版本自带 SCSS 编译，后面主题需要。</p>
<p>主题选了 <a href="https://github.com/adityatelange/hugo-PaperMod">PaperMod</a>。原因很简单：干净、快、功能够用。暗色模式、搜索、目录、代码高亮、多语言——开箱即用，不需要自己从零写前端。用 git submodule 引入，这样主题更新的时候只需要拉一下 submodule 就行：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">hugo new site blog <span class="o">&amp;&amp;</span> <span class="nb">cd</span> blog
</span></span><span class="line"><span class="cl">git init
</span></span><span class="line"><span class="cl">git submodule add --depth<span class="o">=</span><span class="m">1</span> https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
</span></span></code></pre></div><h2 id="配置一个-yaml-文件搞定大部分事情">配置：一个 YAML 文件搞定大部分事情</h2>
<p>Hugo 的配置集中在 <code>hugo.yaml</code> 一个文件里（也支持 toml 和 json，我习惯 yaml）。我的博客是中英双语的，中文是默认语言放在根路径，英文加 <code>/en/</code> 前缀。配置大概长这样：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">defaultContentLanguage</span><span class="p">:</span><span class="w"> </span><span class="l">zh</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">defaultContentLanguageInSubdir</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">  </span><span class="c"># 中文不加前缀</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">languages</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">zh</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">languageName</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;中文&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">weight</span><span class="p">:</span><span class="w"> </span><span class="m">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Forest&#39;s Blog&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">params</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">author</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;北海&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">en</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">languageName</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;EN&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">weight</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Forest&#39;s Blog&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">params</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">author</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Chunhao Zhang&#34;</span><span class="w">
</span></span></span></code></pre></div><p>双语文章的文件命名用后缀区分：中文 <code>build-blog-with-hugo.md</code>，英文 <code>build-blog-with-hugo.en.md</code>。Hugo 会自动把它们关联起来，语言切换的时候跳到对应版本。</p>
<p>不过这个&quot;自动关联&quot;在实际使用时踩了个坑——后面会说。</p>
<h2 id="部署到-cloudflare-pages">部署到 Cloudflare Pages</h2>
<p>选 Cloudflare Pages 而不是 GitHub Pages，主要考虑两点：一是国内访问 GitHub 不稳定，CF 有全球 CDN 节点；二是 CF Pages 的构建和部署体验比 GitHub Actions 简单很多，推代码就自动构建。</p>
<p>但是，Cloudflare 的 Dashboard 设计让我困惑了好一会儿。</p>
<p>点进 &ldquo;Workers &amp; Pages&rdquo; 之后，默认界面显示的是 Workers（Serverless Functions），Pages 的入口藏在页面底部一个不起眼的 &ldquo;Looking to deploy Pages? Get started&rdquo; 链接里。我一开始以为 Pages 被合并到 Workers 里了，来回找了几分钟才发现这个链接。</p>
<p>找到入口之后就顺利了：连接 GitHub 仓库，选择 Hugo 预设，构建命令 <code>hugo --minify</code>，输出目录 <code>public</code>。有一个<strong>必须手动设置的环境变量</strong>：</p>
<table>
  <thead>
      <tr>
          <th>环境变量</th>
          <th>值</th>
          <th>说明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>HUGO_VERSION</code></td>
          <td><code>0.160.0</code></td>
          <td>不设置的话 CF 用的默认版本太旧，构建会出问题</td>
      </tr>
  </tbody>
</table>
<p>部署完拿到一个 <code>blog-6sm.pages.dev</code> 的域名。后续可以绑定自定义域名，但免费域名先用着也没问题。</p>
<h2 id="语言切换的坑">语言切换的坑</h2>
<p>部署上线之后，我发现了一个让人恼火的 bug：在文章页面点击语言切换（中文 ↔ EN），不管当前在哪篇文章，都会跳回首页。</p>
<p>翻了 PaperMod 的源码才发现，默认的 <code>header.html</code> 模板用的是 <code>site.Home.Translations</code> 来生成语言切换链接——也就是说，它永远指向首页的翻译版本，而不是当前页面的翻译版本。</p>
<p>修复方法是在项目的 <code>layouts/partials/</code> 下创建同名的 <code>header.html</code>，覆盖主题模板。Hugo 的模板加载优先级是项目目录 &gt; 主题目录，所以只需要把主题的 header 复制过来，改一行：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go-html-template" data-lang="go-html-template"><span class="line"><span class="cl"><span class="cp">{{-</span><span class="w"> </span><span class="nx">$translations</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="na">.Translations</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl"><span class="cp">{{-</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="k">not</span><span class="w"> </span><span class="nx">$translations</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl">  <span class="cp">{{-</span><span class="w"> </span><span class="nx">$translations</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">site</span><span class="na">.Home.Translations</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl"><span class="cp">{{-</span><span class="w"> </span><span class="k">end</span><span class="w"> </span><span class="cp">}}</span>
</span></span></code></pre></div><p>优先用当前页面的 <code>.Translations</code>，没有翻译的时候才 fallback 到首页。这个改动不大，但确实是 PaperMod 的一个设计缺陷——多语言站点里，用户在文章页切语言跳到首页，体验是割裂的。</p>
<h2 id="评论系统giscus">评论系统：Giscus</h2>
<p>评论系统用的 <a href="https://giscus.app/">Giscus</a>，基于 GitHub Discussions。选它是因为不需要额外的后端服务，评论数据存在 GitHub 仓库的 Discussions 里，对开源博客来说是最自然的方案。</p>
<p>配置时有一个不太直觉的地方：Discussion 分类要选 <strong>Announcements</strong>。这个分类的特殊之处在于，只有仓库管理员能创建新的 Discussion（对应创建一篇文章的评论区），但所有人都可以回复。如果选了 General 之类的开放分类，任何人都能随意创建 Discussion，评论区会变得混乱。</p>
<p>Giscus 还需要处理暗色模式适配。我在 <code>comments.html</code> 里用 <code>MutationObserver</code> 监听 <code>body</code> 的 class 变化，当用户切换主题时动态更新 Giscus 的 iframe 主题：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">observer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">MutationObserver</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">isDark</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">classList</span><span class="p">.</span><span class="nx">contains</span><span class="p">(</span><span class="s1">&#39;dark&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">theme</span> <span class="o">=</span> <span class="nx">isDark</span> <span class="o">?</span> <span class="s1">&#39;noborder_dark&#39;</span> <span class="o">:</span> <span class="s1">&#39;noborder_light&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">iframe</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">&#39;iframe.giscus-frame&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nx">iframe</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">iframe</span><span class="p">.</span><span class="nx">contentWindow</span><span class="p">.</span><span class="nx">postMessage</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span> <span class="nx">giscus</span><span class="o">:</span> <span class="p">{</span> <span class="nx">setConfig</span><span class="o">:</span> <span class="p">{</span> <span class="nx">theme</span> <span class="p">}</span> <span class="p">}</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="s1">&#39;https://giscus.app&#39;</span>
</span></span><span class="line"><span class="cl">        <span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">observer</span><span class="p">.</span><span class="nx">observe</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">,</span> <span class="p">{</span> <span class="nx">attributes</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">attributeFilter</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;class&#39;</span><span class="p">]</span> <span class="p">});</span>
</span></span></code></pre></div><p>这样切换暗色模式时，评论区的主题会跟着变，不会出现页面是暗色但评论区还是白色的割裂感。</p>
<h2 id="其他零碎的配置">其他零碎的配置</h2>
<p><strong>KaTeX 数学公式</strong>，条件加载。只有在文章的 frontmatter 里设了 <code>math: true</code> 才会引入 KaTeX 的 CSS 和 JS，不影响其他文章的加载速度。</p>
<p><strong>robots.txt</strong> 显式允许了 AI 爬虫（GPTBot、ClaudeBot、PerplexityBot）。现在越来越多的站点默认屏蔽 AI 爬虫，但对于一个希望被更多人和 AI 系统引用的技术博客来说，开放抓取是必要的。</p>
<p><strong>代码高亮</strong>用的 Hugo 内置的 Chroma 引擎，主题设置成 <code>dracula</code>。PaperMod 自带代码复制按钮，不需要额外配置。</p>
<h2 id="当前的目录结构">当前的目录结构</h2>
<p>最终项目的文件结构长这样：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">blog/
</span></span><span class="line"><span class="cl">├── hugo.yaml                    # 一切配置的起点
</span></span><span class="line"><span class="cl">├── content/
</span></span><span class="line"><span class="cl">│   ├── posts/                   # 文章
</span></span><span class="line"><span class="cl">│   ├── about.md / about.en.md   # 关于页面
</span></span><span class="line"><span class="cl">│   ├── archives.md              # 归档
</span></span><span class="line"><span class="cl">│   └── search.md                # 搜索
</span></span><span class="line"><span class="cl">├── layouts/partials/
</span></span><span class="line"><span class="cl">│   ├── header.html              # 修复语言切换
</span></span><span class="line"><span class="cl">│   ├── comments.html            # Giscus 评论
</span></span><span class="line"><span class="cl">│   ├── extend_head.html         # KaTeX + Schema
</span></span><span class="line"><span class="cl">│   └── math.html                # KaTeX 脚本
</span></span><span class="line"><span class="cl">├── static/
</span></span><span class="line"><span class="cl">│   ├── favicon.ico              # 地球图标
</span></span><span class="line"><span class="cl">│   └── _headers                 # CF 缓存策略
</span></span><span class="line"><span class="cl">└── themes/PaperMod/             # git submodule
</span></span></code></pre></div><p>没什么多余的文件。静态站点的好处就是结构清晰，不需要数据库，不需要服务器，不需要 Docker。一个 YAML 配置文件，几个 Markdown 文件，几个 HTML 模板，就是一个完整的网站。</p>
<h2 id="回头看">回头看</h2>
<p>整个搭建过程大概花了一个下午。最耗时间的不是 Hugo 本身——Hugo 的文档写得不错，上手很快——而是那些&quot;本应该很简单但就是不顺&quot;的环节：Cloudflare Dashboard 找不到 Pages 入口、语言切换跳首页、Giscus 分类选错导致评论区混乱。</p>
<p>这些问题都不难，但都需要你真的碰到了、花时间排查了，才知道怎么回事。写博客记录下来，下次就不用再踩一遍。</p>
<p>博客搭好了，接下来该写点正经文章了。</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
