跳轉到主要內容

Felimet Hub — 網站維護憲章(給 AI 維護者)

這個 repo 是 Felimet Hub 個人網站(線上 www.jmcores.com)的原始碼,平台是 Mintlify(docs.json 驅動的文件站),雙語(繁體中文 zh-Hant 為主、English 為輔)。設計基調 wabi-sabi 暖色。 維護者預設用自然語言下指令(例:「幫我加一篇關於 vLLM 部署的筆記」「把 Schlieren 那篇標成精選」「準備發布」)。本檔 + .claude/skills/ 是把那些自然語言對應到正確、可重現操作的單一事實來源。動手前先讀本檔對應段落,不要憑印象改。

1. 環境與指令(本地驗證不需帳號)

動作指令說明
安裝/驗證設定npx -y mint@latest validatestrict build 驗證,exit 0 才算過。CI 與發布前必跑
本地預覽npx -y mint@latest dev --port 3001port 3000 常被占,固定用 3001。背景跑
壞連結掃描npx -y mint@latest broken-links發布前選用
重產畫廊資料node scripts/gen-gallery.mjs改任何畫廊文章 frontmatter 後必跑
需求:Node >= 20.17(實測 v24 OK)。mint dev 起來後 curl 輪詢 http://localhost:3001/ 回 200 再截圖。收工用 PowerShell Get-NetTCPConnection -LocalPort 3001 -State Listen 找 PID kill。 HMR 規則(重要)
  • .mdx / .css / .svg 改動 → dev 熱更新會生效。
  • docs.json / snippets/*.jsx 改動 → 必須重啟 dev,HMR 不重載,會 serve 舊 chunk 騙人。

2. 目錄結構與檔案落點

jmcores-docs/
├── docs.json              # 唯一導覽/主題設定來源:tabs、languages、色票、字型、logo、footer
├── style.css             # wabi-sabi 自訂層(Mintlify 自動載入,接在框架樣式後)
├── footer-copyright.js   # 注入 footer 可點 copyright 行(含 /privacy 連結);Mintlify 自動載入根目錄 .js
├── index.mdx             # 首頁(mode: custom,乾淨 landing)
├── about.mdx / about/journey.mdx
├── privacy.mdx
├── projects/  notes/  publications/   # 繁中內容(root = zh-Hant,無語言前綴)
│   └── */overview.mdx                  # 各區畫廊頁(import Gallery + 對應資料)
├── en/                    # 英文鏡像(與 root 同結構,路徑前綴 /en)
├── snippets/
│   ├── gallery.jsx        # 畫廊 React 元件(篩選 chip + 排序,useState)
│   ├── gallery-data.jsx   # 自動產生,勿手改(gen-gallery.mjs 輸出)
│   ├── arch-flow.jsx      # 互動式架構/資料流檢視器(ArchFlow,專案頁 ## 專案架構 用,useState + 自帶明暗主題)
│   ├── option-picker.jsx  # 可重用方案/版本選擇器(OptionPicker,多方案專案:Bitwarden/RustDesk/SAM2…)
│   ├── stale-validator.jsx# 溫濕度頁專用:四訊號失聯驗證互動演示(StaleValidator)
│   ├── upload-demo.jsx    # Cloudflare R2 頁專用:上傳動畫 mock(UploadDemo,useState + useEffect)
│   └── pub-meta.jsx       # 論文中繼資料 pills 元件
├── images/                # 所有圖:mark/wordmark logo、lobe/ AI 品牌 icon、skill-icons/ 技能 icon、各文章圖(含子資料夾如 cuda-setup/)
├── scripts/
│   ├── gen-gallery.mjs    # 掃本 repo frontmatter → gallery-data.jsx(雙語)
│   ├── og-cover.html      # OG 社群卡產生器(1200x630),Playwright 截圖 → images/og-cover.png
│   └── *.mjs              # 一次性遷移工具(convert/fix-*),日常維護用不到
└── .github/workflows/update-gallery.yml  # push 改內容自動重產 gallery-data
圖片落點:文章圖放 images/,多圖的文章開子資料夾(如 images/cuda-setup/fig1.png),MDX 以絕對路徑引用 /images/cuda-setup/fig1.png

3. Frontmatter Schema(畫廊靠這些欄位)

每篇納入畫廊的文章(projects / notes / publications,overview 除外)frontmatter 至少:
---
title: "標題"
description: "一句話描述(畫廊卡片摘要,> 88 字會截斷)"
tags: ["標籤A", "標籤B"]      # 畫廊篩選用
featured: true                # 選填,精選排前
order: 1                       # 選填,featured 內排序(小在前,預設 999)
date: "2025-06"               # publications 排序用(新→舊)
# --- 僅 publications ---
pubType: "journal"            # journal / conference
venue: "IEEE Trans. ..."      # 期刊/會議名(畫廊卡片顯示)
confType: ""                  # 選填
award: ""                     # 選填
draft: true                   # 設了就不上站、不進畫廊(gen-gallery 跳過)
---
Mintlify 忽略它不認得的 key,所以這些自訂欄位安全。新文章一定要帶 tags(否則畫廊篩選缺項)。

4. 雙語原子規則(i18n 不能半開)

docs.jsonnavigation.languages 一旦啟用,每個語言的內容必須齊全,否則切到該語言會空白破頁。 鐵則:任何納入導覽的頁面,root(繁中)與 en/(英文)必須同時存在、同時登記進 docs.json 的兩個語言區塊。 新增一頁 = 建兩個檔 + 改 docs.json 兩處。只做單語 = 破站。
  • root 路徑:notes/foo/bar.mdx → 網址 /notes/foo/bar
  • en 路徑:en/notes/foo/bar.mdx → 網址 /en/notes/foo/bar
  • 英文頁的內部連結要加 /en 前綴。

5. 畫廊維護

  • 資料來源:scripts/gen-gallery.mjs本 repo root + en/ 的 frontmatter,輸出 snippets/gallery-data.jsx(exports projects/notes/publications + projectsEn/notesEn/publicationsEn)。
  • 改了任何畫廊文章的 title/description/tags/featured/order/draft → node scripts/gen-gallery.mjs,否則畫廊不同步。
  • GitHub Action(.github/workflows/update-gallery.yml)會在 push 改內容時自動重產,但本地驗證前自己先跑一次比較準。
  • gallery-data.jsx 標頭寫「自動產生勿手改」,要改畫廊內容去改來源 MDX frontmatter,不是改這個檔。

6. 設計系統(沿用,不要亂動)

  • 色票(docs.json colors):primary #bf7551(sienna 主互動色)、light #cf8a68、dark #a85f3f。背景 cream #F9F7F2 / slate #1F1F21
  • 字型(docs.json fonts):heading Crimson Pro、body Noto Sans TC。兩者皆 Google Fonts,採 family-only 寫法 = Mintlify 自動走 Google Fonts API 載入(官方:指定 Google Font family 名即自動載入,無需 source URL)。不要為它們加 source,那會切成自架 woff2、脫離 Google Fonts API。要換字型才動 family,否則別碰。
  • 圖示(docs.json icons.library: "lucide"):全站 icon=Lucide所有 icon 名稱必須是 Lucide 名(非 FontAwesome)。新增頁面用 Lucide 名(如 triangle-alertwarningmailenvelopefile-textdocument)。Lucide 核心已移除 brand icon(github/linkedin 等):brand 用 icon={<svg … fill="currentColor"/>} 內嵌 SVG(about 頁的 GitHub/LinkedIn/ORCID 即此法),保留品牌外形又隨主題色。
  • 社群分享(docs.json seo.metatags):Open Graph + Twitter Card,全站預設 images/og-cover.png(1200x630 品牌卡,由 scripts/og-cover.html 經 Playwright 截圖產生)。細節見 §8.4。
  • logo:一體式 wordmark SVG(images/logo-wordmark.svg 亮 / logo-wordmark-dark.svg 暗,含 JM mark + Georgia「Felimet Hub」字)。docs.json logo 指這兩個。mark.svg(純 JM)目前未用於 nav,留作他用。
  • 自訂色一律走 style.css 的具名 class(如畫廊 .g-*),不要用 var(--sl-*)(那是 Starlight 變數,Mintlify 沒有,會 fallback 出錯)。暗色模式靠 html.dark

7. 部署(這步要本人,AI 做不了;步驟已查證 Mintlify 官方文件)

新站走 Mintlify 託管(app.mintlify.com),不是 Cloudflare Pages(舊 Astro 站才是)。自訂網域 = felimet-hub.jmcores.com(子網域,非 www)。流程:
  1. jmcores-docs 推上 GitHub repo(已建:github.com/felimet/felimet-hub,private)。
  2. app.mintlify.com → 裝 Mintlify GitHub App 連 repo(Settings → GitHub App → Install)。之後 push 自動 build+deploy。
  3. dashboard 加自訂網域 felimet-hub.jmcores.com → 它給兩筆 TXT(_acme-challenge.felimet-hub_cf-custom-hostname.felimet-hub)先加進 Cloudflare DNS,等兩筆綠勾驗證過再動 CNAME。
  4. CNAME:felimet-hub → cname.mintlify.buildersCloudflare 這筆設 DNS-only(關 proxy/灰雲) — 官方明講開 proxy 會擋憑證簽發。
  5. (子網域不影響舊站)舊 www/根網域的 Cloudflare Pages 記錄可保留;felimet-hub 是新獨立子網域。
  6. 等 DNS 傳播(1-24h),docs.json 設 canonical 指向 felimet-hub.jmcores.com。
Cloudflare 仍當 DNS provider(DNS-only)。要保留 CF proxy/WAF 在前需 Worker 進階做法(官方 /deploy/cloudflare),個人站非必要。 參考:mintlify.com/docs/customize/custom-domain、/deploy/cloudflare、/deploy/github。

7.1 版本控制與部署流程(每次修改都版控)

  • repo:github.com/felimet/felimet-hub(private)。預設分支 main
  • 每次修改後 commit(預設只 commit,不 push):Conventional Commits(feat:/fix:/docs:/chore:/refactor:),單一職責,body 說 why。改畫廊文章 frontmatter → 先 node scripts/gen-gallery.mjs 再 commit。
  • push 只在使用者明說「push」時才做(使用者偏好,2026-06-08 起)。因為 push = 觸發 Mintlify 自動部署上線,使用者要自行掌控何時上線。平時累積 commit,等他說 push 再一次推。
  • push 到 main 後才會 → (a) .github/workflows/validate.ymlmint validate CI;(b) .github/workflows/update-gallery.yml 自動重產 gallery-data;(c) Mintlify GitHub App 自動 build+deploy(這才是「自動部署」,不是 GitHub Actions — Actions 只做驗證與畫廊重產)。push 前若遠端有新 commit(CI gallery 或 PR)先 git pull --rebase
  • 機密永不進 git(.gitignore 已排除 .env*node_modules.mintlify.playwright-mcptmp/)。

8. 踩雷清單(前人流血換的,照做省時間)

  1. snippet 常數放元件內:Mintlify snippet 只認 export 的元件,module 層級的 const 不在 render scope → ReferenceError 整塊空白。常數寫進元件函式內。
  2. 改 snippet / docs.json 要重啟 dev:HMR 不重載這兩類,會 serve 舊版。
  3. 沒有 var(--sl-*):Starlight 變數在 Mintlify 不存在,誤用會 fallback(例:暗色卡片變白底、文字隱形)。用 style.css 具名 class。
  4. 原生 HTML 屬性要轉 JSX:MDX 裡 style="..." 字串 / frameborder / class 會 React error #62 整頁 500。要 style={{物件}}className、JSX 屬性。
  5. SVG logo 切邊:先查 SVG 內部殘留的 clipPath(會把內容裁回舊框),不要只調 viewBox。<img> 載的 SVG 吃不到 web font(Crimson Pro),文字寬不可靠 → 要嘛 textLength 釘死、要嘛轉 path、要嘛用已內嵌字體的 SVG(現用的 wordmark 內嵌 Georgia)。
  6. content 頁圖片 404:多圖文章的圖片子資料夾要完整放進 images/,MDX 用絕對路徑 /images/<夾>/<檔>。發布前 grep 全站圖片引用對檔案存在性。
  7. Powered by Mintlify:免費/Pro 用 CSS 隱藏違反 ToS(white-label 是 Enterprise)。現 style.css 有隱藏規則 + 警告註解;反悔刪那條即可。
  8. draft 文章draft: true 不上站、不進畫廊。目前約 13 篇草稿刻意不遷,要補才動。
  9. footer 最多 4 欄:docs.json footer.links 超過 4 個 group → validate 直接擋(maximum of 4 links columns)。要多分類得合併。現況 4 欄=探索 / 學術(ORCID、WoS)/ 連結(GitHub、LinkedIn、Email)/ 實驗室(ISSP & MES LAB、IMES LAB)。
  10. copyright 行可點連結 = 自訂 JS:Mintlify footer 無自由文字欄、CSS ::after 是生成內容不可點。copyright 行(含可點的「隱私權保護政策」→ /privacy)由 footer-copyright.js 注入真 DOM(#custom-copyright),樣式在 style.css。Mintlify 會自動載入 repo 根目錄任何 .js(等同每頁 <script>,官方 /customize/custom-scripts)。SPA 換頁用 MutationObserver + id 去重保連結持續存在。改 copyright 文字/privacy 連結就改這支 .js。

8.1 內容標點與用語規範(house style,發布前必檢)

  • 全站禁 em-dash( U+2014),以及當句中破折號用的 spaced en-dash( U+2013)。 句中破折號一律改寫:英文內文視語氣用 : / ; / ,,中文內文用全形 / / ;對偶插入語(A — … — B)改括號或前後逗號。
  • 例外(屬正確排版,保留):數字與範圍的 en-dash(60–100°C0–250、頁碼 2345–2367);程式碼、識別符、CLI 旗標、英文複合詞裡的連字符 -
  • 驗收:發布前 rg -n '—' **/*.mdx 應 0 命中(數字範圍的 en-dash 可留)。zhtw-writing 這類寫作指南也照清,它沒在講 em-dash 本身,內文破折號一樣換掉。
  • 固定術語:journey 那組 tag 用 Agency Agents(不是 AI Agency / Agentic AI;About 內文的「Agentic AI」是標準術語,另計);標註(不是標注)。中文用語照 CNS/IEEE 台灣慣例(資料 / 軟體 / 網路 / 演算法 / 畫格 / 位元組)。
  • 來源:使用者全域偏好「不用 em dash 跟 en dash」+ 2026-06-08 全站清除指令。新增 / 改寫任何 .mdx 都套這條,別把 em-dash 帶回來。
  • 英文半形標點(所有頁面):英文片段/語句一律用半形直引號 ' "(ASCII),不用彎引號 '’“” 或全形 '"。中文內文照舊用全形標點。驗收:rg -nP '[\x{2018}\x{2019}\x{201C}\x{201D}]' en/ 應 0 命中。

8.2 專案頁模板(projects/*.mdx,2026-06-08 起固定)

9 個專案頁統一這套結構,新增專案照抄。黃金範本:projects/gpustack-api.mdx + en/projects/gpustack-api.mdx
  • 內容來源:從該 repo 的 README 與 docs/ 提取真實內容(gh api "repos/felimet/<repo>/readme" -H "Accept: application/vnd.github.raw"),不要憑 frontmatter 或印象編。標題與內文不誇大,像作者本人寫的,去 emoji / badge / 行銷詞。
  • 章節順序(名稱可依內容微調):頂部 tag 列(inline code 以 · 串,與 frontmatter tags 一致)→ 專案概述 → 核心功能 → 專案架構 → 技術棧(選用)→ 快速開始 → 配置比較(多方案才放,表格)→ 注意事項 / 安全提醒(<Warning>)→ 實際應用面 → 相關連結。
  • 專案架構用互動式 <ArchFlow> 元件import { ArchFlow } from '/snippets/arch-flow.jsx'; 放 frontmatter 後):資料流/管線轉成 nodes={[{ label, detail }, …]}(4-7 個,en 頁加 lang="en"),點/hover 看各階段說明。目錄/檔案樹不是流程,維持 fenced code block。無真正流程的頁(如 SAM2)不硬塞。
  • 快速開始用 <Steps><Step title="…"> 元件(非 markdown 數字清單),渲染為編號圓圈 + 標題 + 框起內容(使用者指定的呈現,適用所有有步驟的頁面)。
  • 相關連結扁平化:底部 ## 相關連結 / ## Links 用 markdown bullet 清單,- GitHub:[felimet/<repo>](url) + 官方外部文件。不用 <Card> 做連結、不寫「原始碼」、不放內部 /notes/... 連結(多為死連結)。
  • 雙語原子:zh projects/<slug>.mdx 與 en en/projects/<slug>.mdx 同步,frontmatter date/order 不動,tags 各專案獨立。

8.3 互動元件設計系統(可重用、跨頁含 Notes)

頁面不只放靜態文字,可嵌入量身的互動 React 元件提升理解與記憶點。此概念不限專案頁,Notes、Publications、About 等任何 .mdx 都能用。 參考來源:Claude Code docs 的 Explore-the-directory / context-window 互動 widget。 設計語言(所有互動元件共用)
  • snippets/<name>.jsxexport const Name = ({ ...props, lang = "zh" }) => {…}
  • Hooks 直接用(useStateuseEffect 為 Mintlify snippet 全域,免 import);常數寫元件函式內(module 層級 const 會 ReferenceError 整塊空白)。
  • 自帶 <style>{css}</style>:用 CSS 變數定義 wabi-sabi 暖色(sienna #bf7551/亮 #cf8a68),.dark .x-root{…} 覆寫暗色,不要用 var(--sl-*)。手機加 @media (max-width:…) 降為單欄。
  • 雙語:吃 lang prop(en 頁傳 lang="en"),UI 字串與資料分 zh/en。資料盡量由 props 傳入,元件本身與內容解耦以利重用。
  • 接入:MDX frontmatter 後 import { Name } from '/snippets/name.jsx';,內文 <Name … />
  • 圖示:元件內用 Lucide,但 不要 import lucide-react(Mintlify snippet 沙箱無 bundler,import npm 套件會整塊空白)。改為內嵌 Lucide SVGfill="none" stroke="currentColor",JSX camelCase 屬性 strokeWidth/strokeLinecap/strokeLinejoin),靠 CSS 變數上色。現況:ArchFlow=workflow、OptionPicker=layers、StaleValidator=signal 各一個 header icon;UploadDemo 的上傳(cloud-upload)/ 檔案(file/package)/ 完成(check)全為內嵌 Lucide。
  • 驗收:mint validate 綠 + mint dev 起來用 Playwright 實測互動(點擊/切換/動畫)與明暗兩模,截圖存證。
現有元件目錄
  • ArchFlow(arch-flow.jsx):資料流/管線,點階段看說明。資料流貼切的頁用。
  • OptionPicker(option-picker.jsx):可重用多方案/版本選擇器,options=[{name,badge?,recommend?,specs:[[k,v]],note}]。Bitwarden 已用;RustDesk 版本、SAM2 安裝路徑、Label Anything 後端等都餵不同資料共用。
  • StaleValidator(stale-validator.jsx):溫濕度頁專用,撥四訊號看 stale 判定。
  • UploadDemo(upload-demo.jsx):R2 頁專用,上傳進度動畫 mock。
每專案量身 map(使用者 2026-06-08「widgets-all」定案,gpustack 保留 ArchFlow):溫濕度=StaleValidator、Bitwarden=OptionPicker、R2=UploadDemo(以上 batch 1 完成);待做:RustDesk/SAM2/Label Anything=OptionPicker 餵各自資料、乳牛跛行=四等級分類演示(新 bespoke)、Synology=憑證決策。原則:每頁挑最貼合其內容的互動模式,不全用同一個;同理可延伸到 Notes(例如環境設定流程、版本相容矩陣、決策樹)。

8.4 SEO 與 Open Graph(社群分享卡,docs.json seo

  • 全站 meta 在 docs.json 頂層 description + seo.metatags(key-value)。seo.indexing: "all" 允許索引。
  • Open Graph / Twitter Card:og:type/og:site_name/og:title/og:description/og:image(+width/height/alt)/og:localetwitter:card: summary_large_image/twitter:image/theme-color。圖一律用絕對網址 https://felimet-hub.jmcores.com/images/og-cover.png
  • 全站預設一張 og 圖seo.metatags.og:image 對所有頁面生效(品牌一致)。要讓某頁有專屬卡,在該頁 frontmatter 設 "og:image": "…" 覆寫(key 帶冒號要加引號,見 §8.1 / Mintlify pages)。
  • og 圖產生流程:scripts/og-cover.html(1200x630,wabi-sabi,字型走 Google Fonts API)→ Playwright 開(file:// 被擋,先 python -m http.server <port> --directory <repo> 餵,navigate http://localhost:<port>/scripts/og-cover.html)→ viewport resize 1200x630 → 等字型 → 截圖 → 存 images/og-cover.png。改品牌文案就改 HTML 重截。
  • 驗收:mint validate 綠;上線後用各平台 OG debugger 或 opengraph.xyz 抽驗。

9. 常見任務 → 對應 skill

  • 新增/更新文章(雙語、frontmatter、登記、重產畫廊)→ .claude/skills/add-content
  • 發布前完整檢查(validate + 畫廊同步 + 壞連結 + render 抽驗)→ .claude/skills/publish-check
skill 是標準流程;本檔是背景知識與鐵則。兩者一起讀。