Blog Publisher — 從 GitHub Tutorial 到 Hugo Blog 的自動發佈工作流教學


1. 概述

本教學說明如何將 AI-Knowledge Template (AIKT) 產出的 GitHub tutorial markdown 自動轉換為 Hugo blog post 並部署到 Netlify。

1.1 解決的問題

AIKT 的 gh-tutorial-qd workflow 會產出大量高品質的 GitHub 專案教學文件(目前已有 161 份 tutorial markdown),但這些內容只存在本地。Blog Publisher 將這些內容自動轉成 blog 文章,讓知識可被搜尋引擎索引、可分享、可累積。

1.2 完整架構


flowchart LR
    subgraph AIKT["AI-Knowledge Template"]
        GH["gh-tutorial-qd\nworkflow"] --> MD["tutorial.md\n(quarkdown 格式)"]
        MD --> QD["tutorial.qd"]
        QD --> HTML["tutorial HTML\n(quarkdown-out/)"]
    end

    subgraph PUBLISH["Blog Publisher"]
        MD --> CONVERT["convert_to_hugo.sh\n(strip frontmatter\n+ mermaid shortcode)"]
        CONVERT --> POST["content/post/\nYYYY-MM-DD-xxx/\nindex.md"]
    end

    subgraph DEPLOY["Deployment"]
        POST --> GIT["git commit + push"]
        GIT --> NETLIFY["Netlify\nauto-deploy"]
        NETLIFY --> LIVE["tpow-001.netlify.app"]
    end

    style AIKT fill:#e7f5ff
    style PUBLISH fill:#fff3bf
    style DEPLOY fill:#d3f9d8


2. Blog 技術架構

2.1 技術棧 (Tech Stack)

元件技術說明
SSG (Static Site Generator; 靜態網站產生器)Hugo 0.145.0Go-based,build 速度極快(42 pages / 171ms)
Themehugo-theme-zen極簡風格,內建 search / sidebar / RSS
HostingNetlifyGit push 自動 CI/CD,免費方案足夠
Domaintpow-001.netlify.appNetlify 子網域
DiagramMermaid.js 11 (CDN)透過自建 shortcode + head partial 支援
FontsInter + Lato + Noto Sans Mono從 quarkdown minimal theme 移植,Google Fonts CDN
Source Banner自建 single.html override自動顯示 stars / forks / language / license
Source repoTPOW-001/TPOW_250401_zenGitHub master branch

2.2 Hugo 目錄結構


graph TD
    ROOT["TPOW_250401_zen/"] --> CONTENT["content/"]
    ROOT --> LAYOUTS["layouts/"]
    ROOT --> STATIC["static/"]
    ROOT --> THEMES["themes/hugo-theme-zen/"]
    ROOT --> CONFIG["hugo.yaml"]
    ROOT --> NETLIFY["netlify.toml"]

    CONTENT --> ABOUT["about.md"]
    CONTENT --> POSTS["post/"]
    POSTS --> P1["2026-05-20-paper-qa/\nindex.md"]
    POSTS --> P2["2026-06-01-taiwan-health-mcp/\nindex.md"]
    POSTS --> P3["2026-06-02-bionemo-framework/\nindex.md"]
    POSTS --> P4["...更多 posts"]

    LAYOUTS --> PARTIALS["partials/\nhead.html\n← Fonts + Mermaid CDN + CSS"]
    LAYOUTS --> SHORTCODES["shortcodes/\nmermaid.html"]
    LAYOUTS --> SINGLE["_default/\nsingle.html\n← Source Banner"]

    style ROOT fill:#339af0,color:#fff
    style CONFIG fill:#ff922b,color:#fff
    style PARTIALS fill:#51cf66,color:#fff
    style SINGLE fill:#845ef7,color:#fff

2.3 Hugo 設定 (hugo.yaml) 關鍵配置

 1# 基本資訊
 2title: "TPOW Lab"
 3baseURL: "https://tpow-001.netlify.app/"
 4languageCode: "zh-TW"
 5
 6# Markdown 渲染 — 必須啟用 unsafe 才能支援 HTML shortcode
 7markup:
 8  goldmark:
 9    renderer:
10      unsafe: true
11
12# 文章設定
13params:
14  buildFuture: true            # 允許未來日期的文章顯示
15  sidebar: true
16  author:
17    name: "TPOW-001"

2.4 Netlify 設定 (netlify.toml)

1[build]
2command = 'hugo'
3publish = 'public'
4
5[build.environment]
6HUGO_VERSION = '0.145.0'
7
8[context.production.environment]
9HUGO_ENV = 'production'

2.5 排版風格(quarkdown minimal theme 移植)

字型來自 quarkdown 的 minimal layout theme,透過 layouts/partials/head.html 注入 Google Fonts CDN:


graph LR
    subgraph QUARKDOWN["Quarkdown Minimal Theme"]
        QH["Heading: Inter"]
        QB["Body: Lato"]
        QC["Code: Noto Sans Mono"]
    end

    subgraph HUGO["Hugo Blog (head.html)"]
        HH["--font-heading: Inter"]
        HB["--font-body: Lato"]
        HC["--font-code: Noto Sans Mono"]
    end

    QH -.->|"移植"| HH
    QB -.->|"移植"| HB
    QC -.->|"移植"| HC

    style QUARKDOWN fill:#e7f5ff
    style HUGO fill:#d3f9d8

用途字型來源CSS 變數
標題 (H1-H6)Inter (wght 400-800)Google Fonts--font-heading
內文Lato (wght 300-700)Google Fonts--font-body
程式碼Noto Sans Mono (wght 400-600)Google Fonts--font-code

2.6 Source Banner(來源資訊條)

每篇含 source_url frontmatter 的文章,標題下方自動顯示 source banner:

1Source: https://github.com/NVIDIA-BioNeMo/bionemo-framework
2⭐ 757 stars  🍴 154 forks  💻 Jupyter Notebook  📜 Apache-2.0

實作於 layouts/_default/single.html(override theme 的 _default/single.html)。Banner 只在文章 frontmatter 有 source_url 時才顯示,不影響一般文章。


3. Mermaid 支援機制

Hugo 原生不支援 Mermaid diagram (Mermaid 圖表)。本專案透過三個元件實現支援:

3.1 架構圖


flowchart TD
    subgraph AUTHOR["文章撰寫"]
        A1["在 md 中寫\n
\ngraph TD\n  A-->B\n
"] end subgraph HUGO["Hugo Build"] B1["shortcodes/mermaid.html\n轉為 pre.mermaid"] --> B2["partials/head.html\n注入 Mermaid CDN"] B2 --> B3["frontmatter\nmermaid: true\n控制是否載入"] end subgraph BROWSER["瀏覽器"] C1["Mermaid.js CDN 載入"] --> C2["document.addEventListener\ninitialize()"] --> C3["pre.mermaid 元素\n渲染為 SVG"] end AUTHOR --> HUGO --> BROWSER style AUTHOR fill:#e7f5ff style HUGO fill:#fff3bf style BROWSER fill:#d3f9d8

3.2 shortcodes/mermaid.html

1<pre class="mermaid">
2{{ .Inner }}
3</pre>

3.3 partials/head.html

 1{{ if .Params.mermaid }}
 2<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
 3<script>
 4  document.addEventListener('DOMContentLoaded', function () {
 5    mermaid.initialize({
 6      startOnLoad: true,
 7      theme: 'default',
 8      securityLevel: 'loose',
 9      fontFamily: '-apple-system, BlinkMacSystemFont, "Noto Sans TC", sans-serif'
10    });
11  });
12</script>
13{{ end }}

3.4 使用條件

  • Frontmatter 必須包含 mermaid: true,否則不載入 CDN(節省頁面 load time)
  • convert_to_hugo.sh 會自動偵測文章中是否有 mermaid shortcode,自動加入 mermaid: true

4. 轉換流程詳解

4.1 完整轉換流程


flowchart TD
    A["輸入:AIKT tutorial.md\n(quarkdown 格式 frontmatter)"] --> B["Step 1: 提取原始 frontmatter\ntitle / date / tags / url\nstars / forks / language / license"]
    B --> C["Step 2: awk 移除原始 frontmatter\n+ 轉換 mermaid fence\n→ Hugo shortcode"]
    C --> D["Step 3: 從目錄路徑\n自動推斷 category\n(bio→Bioinformatics\nagent→AI-Agent)"]
    D --> E["Step 4: 清理 tags\n移除原始引號\n統一 JSON array 格式"]
    E --> F["Step 5: printf 寫入\nHugo frontmatter\ntitle / author / date\ncategories / tags\nsource_url / github\nstars / forks / language\nlicense / mermaid"]
    F --> G["Step 6: cat 附加 body\n→ index.md"]

    style A fill:#ff8787,color:#fff
    style B fill:#ff922b,color:#fff
    style F fill:#339af0,color:#fff
    style G fill:#51cf66,color:#fff

4.2 Frontmatter 格式轉換對照

轉換前(AIKT quarkdown 格式)

 1---
 2title: "Tutorial: NVIDIA-BioNeMo/bionemo-framework — 完整解讀"
 3date: 2026-06-02
 4source: github
 5url: https://github.com/NVIDIA-BioNeMo/bionemo-framework
 6owner: NVIDIA-BioNeMo
 7repo: bionemo-framework
 8language: Jupyter Notebook
 9stars: 757
10forks: 154
11license: Apache-2.0
12tags: [tutorial, bionemo, biopharma-foundation-model, esm2, ...]
13---

轉換後(Hugo 格式 v2 — 保留完整 metadata)

 1---
 2title: "Tutorial: NVIDIA-BioNeMo/bionemo-framework — 完整解讀..."
 3author: "TPOW-001"
 4date: 2026-06-02
 5categories: ["Bioinformatics"]
 6tags: ["tutorial", "bionemo", "biopharma-foundation-model", "esm2", "amplify",
 7       "evo2", "geneformer", "codonfm", "moco", "drug-discovery", "nvidia"]
 8source_url: "https://github.com/NVIDIA-BioNeMo/bionemo-framework"
 9github: "NVIDIA-BioNeMo/bionemo-framework"
10stars: 757
11forks: 154
12language: "Jupyter Notebook"
13license: "Apache-2.0"
14mermaid: true
15---

v1 → v2 差異對照

欄位v1v2
title從 H1 提取優先從原始 frontmatter,fallback H1
date手動指定自動提取 date / saved_at / 檔名
tags固定 ["tutorial", "bioinformatics"]保留原始所有 tags
category手動指定從目錄路徑自動推斷
source_url自動提取 url / github_url
stars / forks自動提取
language / license自動提取

4.3 Mermaid 語法轉換對照

轉換前(標準 markdown)

1

flowchart TD
    A --> B

轉換後(Hugo shortcode)

1{{< mermaid >}}
2flowchart TD
3    A --> B
4{{< /mermaid >}}

4.4 執行方式(v2 — 簡化參數)

 1# v2 只需 3 個參數(date / category / tags 全自動提取)
 2bash scripts/convert_to_hugo.sh \
 3  "<tutorial.md 路徑>" \
 4  "<Hugo post 目錄>" \
 5  "[author]"              # 預設 TPOW-001
 6
 7# 實際範例
 8bash scripts/convert_to_hugo.sh \
 9  "projects/260520 Github repo/260602 bionemo-framework/quarkdown/2026-06-02-tutorial-bionemo-framework.md" \
10  "/tmp/TPOW_250401_zen/content/post/2026-06-02-bionemo-framework"
11# → 自動提取 date=2026-06-02, category=Bioinformatics, tags=22個, stars=757, ...

v1 vs v2 參數對比

1# v1(5 個參數,手動指定 date / category)
2bash convert_to_hugo.sh <md> <post_dir> <date> <category> <author>
3
4# v2(2-3 個參數,全自動)
5bash convert_to_hugo.sh <md> <post_dir> [author]

5. 部署流程

5.1 端到端發佈流程


sequenceDiagram
    participant U as User
    participant C as Claude Code
    participant S as convert_to_hugo.sh
    participant G as GitHub
    participant N as Netlify

    U->>C: blog-publish: path/to/tutorial.qd
    C->>C: 讀取 .qd 對應的 tutorial.md
    C->>C: 提取 date / category
    C->>S: 執行 convert_to_hugo.sh
    S->>S: strip frontmatter + mermaid shortcode
    S-->>C: index.md 產出
    C->>G: git add + commit + push
    G->>N: webhook trigger
    N->>N: hugo build (0.145.0)
    N-->>U: 部署完成 (1-2 min)
    C->>U: Discord reply with URL

5.2 Git 操作流程

 1# 1. Clone blog repo (若尚未 clone)
 2git clone https://github.com/TPOW-001/TPOW_250401_zen.git /tmp/TPOW_250401_zen
 3
 4# 2. 轉換 tutorial
 5bash scripts/convert_to_hugo.sh <args...>
 6
 7# 3. 本地驗證
 8cd /tmp/TPOW_250401_zen && hugo --gc --minify
 9
10# 4. Commit + Push
11git add content/post/<new-post>/
12git commit -m "feat: add <post-name> tutorial post"
13git push origin master
14
15# 5. 等待 Netlify 自動部署 (1-2 min)

6. 已發佈文章清單

6.1 Bio 系列(第一批 3 篇,2026-06-12 發佈)

日期文章行數Mermaid來源
2026-05-20paper-qa — Agentic RAG for Scientific Literature5271 圖260520 paper-qa
2026-06-01Taiwan-Health-MCP — 台灣醫療資料 MCP 伺服器教學4141 圖260601 Taiwan-Health-MCP
2026-06-02NVIDIA BioNeMo Framework — 蛋白質/基因/藥物 AI 引擎教學1,3796 圖260602 bionemo-framework

6.2 素材庫統計

系列可用 tutorial 數說明
Bio / Medical14最核心,最符合專業背景
AI Agent / Claude15Claude Code + Agent 生態系
DevTools20+開發工具、self-hosted、3D 等
NVIDIA10+BioNeMo / Cosmos / GR00T / Nemotron
其他100+金融、動畫、影片製作、面試等
合計161全部來自 260520 Github repo/

7. 故障排除

7.1 常見問題

問題原因解法
Mermaid 圖不渲染frontmatter 缺 mermaid: true確認 convert script 有偵測到 mermaid
Mermaid 圖顯示原始碼瀏覽器無網路(CDN 載入失敗)連網後重新整理
HTML 標籤被 stripgoldmark.renderer.unsafe 未啟用確認 hugo.yaml 有 unsafe: true
文章不出現日期是未來確認 params.buildFuture: true
Hugo build 失敗shortcode 語法錯誤檢查 {{< mermaid >}} 配對

7.2 本地測試

 1# 下載 Hugo (一次性)
 2curl -sL "https://github.com/gohugoio/hugo/releases/download/v0.145.0/hugo_extended_0.145.0_linux-amd64.tar.gz" | tar xz hugo
 3./hugo version
 4
 5# Build 測試
 6cd /tmp/TPOW_250401_zen
 7./hugo --gc --minify
 8
 9# 本地預覽
10./hugo server -D  # http://localhost:1313

8. 相關檔案索引

 1projects/260612 blog-publisher/
 2├── scripts/
 3│   └── convert_to_hugo.sh           ← 核心轉換 script (v2)
 4├── quarkdown/
 5│   └── 2026-06-12-blog-publisher-tutorial.qd
 6├── quarkdown-out/
 7│   └── 01-tutorial/index.html       ← 本教學的 HTML 版
 8└── (本教學 md 存於 inbox/)
 9
10AIKT Skill:
11.claude/skills/blog-publish/
12└── SKILL.md                          ← blog-publish skill 定義 (Layer 21)
13
14Blog repo (GitHub):
15TPOW-001/TPOW_250401_zen
16├── hugo.yaml                         ← 網站設定(Inter+Lato+NotoSansMono 字型)
17├── netlify.toml                      ← 部署設定(Hugo 0.145.0)
18├── content/
19│   ├── about.md
20│   └── post/                         ← 所有 blog 文章
21├── layouts/
22│   ├── _default/single.html          ← Source Banner(stars/forks/lang/license)
23│   ├── partials/head.html            ← Fonts CDN + Mermaid CDN + CSS 變數
24│   └── shortcodes/mermaid.html       ← Mermaid shortcode
25└── themes/hugo-theme-zen/            ← Zen 主題(base)

9. blog-publish Skill 使用說明

9.1 觸發方式

1blog-publish: <qd 檔案路徑>

或自然語言:

1幫我把 projects/260520 Github repo/260602 bionemo-framework/quarkdown/2026-06-02-tutorial-bionemo-framework.qd 發到 blog

9.2 Skill 執行流程


flowchart TD
    A["使用者指定 .qd 檔路徑"] --> B["找到對應的 tutorial.md\n(同目錄,副檔名換 .md)"]
    B --> C["從檔名提取 date\n(YYYY-MM-DD 格式)"]
    C --> D["從目錄名推斷 category\n(bio / ai-agent / devtools)"]
    D --> E["Clone blog repo\n(git clone --depth 1)"]
    E --> F["執行 convert_to_hugo.sh"]
    F --> G["hugo build 驗證"]
    G --> H{"Build 成功?"}
    H -->|Yes| I["git add + commit + push"]
    H -->|No| J["回報錯誤\n不 push"]
    I --> K["Discord reply\n附上 blog URL"]

    style A fill:#339af0,color:#fff
    style I fill:#51cf66,color:#fff
    style J fill:#ff6b6b,color:#fff

9.3 Category 自動判斷規則

目錄名關鍵字Category
bio / bionemo / drug / medical / health / causalbench / retrosynthesis / paper-qa / turbovecBioinformatics
claude / agent / mem0 / skill / mcp / anthropic / hivemindAI-Agent
其他DevTools