Skip to main content

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

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

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

需求: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. 目錄結構與檔案落點

圖片落點:文章圖放 images/,多圖的文章開子資料夾(如 images/cuda-setup/fig1.png),MDX 以絕對路徑引用 /images/cuda-setup/fig1.png

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

每篇納入畫廊的文章(projects / notes / publications,overview 除外)frontmatter 至少:
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,否則別碰。
  • 西文散文字形 Noto Serif(2026-06-12 使用者指定):docs.json fonts 只有兩槽,第三 family 由根目錄 fonts-noto-serif.js 注入 Google Fonts 載入,style.css 散文堆疊把 "Noto Serif" 插在 "Noto Sans TC" 前(拉丁碼位走 serif,CJK 自然回退)。標題仍 Crimson Pro、code 仍等寬,皆不受影響。
  • 圖示(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 + thumbnails):逐頁 OG(Mintlify 自動產,品牌底圖 images/og-background.png + thumbnails.theme),首頁用完整設計卡 images/og-cover.png。細節見 §8.4 與 .claude/rules/og-cards.md
  • 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
  • 散文排版:段落級散文(含 Mintlify 的 span[data-as="p"]、p、li、blockquote、dd)兩端對齊(justify + 英文 hyphens 斷字),標題/表格欄/圖說/code 維持 start(實作在 style.css「散文兩端對齊」段,2026-06-11 定案)。渲染層引號規則(直引號 JS、QuoteLatin 備援)見 §8 踩雷 11 與 §8.1;細節住 .claude/rules/house-style.md

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。
  11. 線上英文出現彎引號 ≠ 源碼髒:Mintlify 的 MDX 渲染器在 build 期對英文散文套 smartypants,把源碼直引號轉成彎引號(U+2018/9、U+201C/D),無 docs.json 開關。別回頭改 .mdx 源碼,源碼本來就直、grep 也會證明 0 命中。修法已就位:quotes-straight.js(根目錄,自動載入)前端換回直引號,勿刪style.cssQuoteLatin @font-face 為 no-JS 備援。注意 Mintlify 把根目錄 .js inline 注入多份(實測同頁 3 份),自訂 script 開頭要 window.__xxxLoaded 旗標去重;且 .js 內禁寫字面彎引號(用 \u 跳脫 / String.fromCharCode),否則 §8.1 驗收 grep 自觸發。細節見 .claude/rules/house-style.md 渲染段。

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 直引號 '(U+0027)與 "(U+0022);英文 contraction/所有格撇號同理(heater'smodel's,不是彎撇號)。不用彎引號(U+2018/U+2019/U+201C/U+201D)或全形(U+FF07/U+FF02)。中文內文照舊用全形標點與全形引號「」『』(U+300C/D、U+300E/F),「修引號」時不要把中文全形引號誤改成 ASCII(不同字元、不在驗收 regex 命中範圍)。
  • 驗收(全 repo,非僅 en/rg -nP '[\x{2018}\x{2019}\x{201C}\x{201D}]' . 應 0 命中。列舉禁用彎引號給人看時一律用 U+xxxx 記法、不貼字面彎引號,否則 grep 永遠有殘留、規範自打臉(本檔即如此書寫)。完整標點與引號規範見 .claude/rules/house-style.md
  • 渲染面(與源碼分開判斷):線上彎引號是 build 期 smartypants 轉的,不是源碼髒(見 §8 踩雷 11)。渲染結果要求直引號(2026-06-11 定案):quotes-straight.js 前端逐字換回 ASCII,code/pre/kbd/samp 跳過、中文「」『』不在範圍;QuoteLatin @font-face(style.css)為 no-JS 備援。驗收:本地 mint dev 起來後以瀏覽器檢查英文散文 document.body.innerText 無 U+2018/9、U+201C/D,中文頁「」對數不變。

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。
  • LamenessGrades(lameness-grades.jsx):乳牛跛行專用,四等級晶片(Normal/Slight/Severe/Stationary,依嚴重度著色)+ GEI/HEI 融合權重滑桿(純示意,不做預測)。
  • CertDecision(cert-decision.jsx):Synology 專用,選流量路徑(橘雲 proxy / 直連)→ 即時給建議憑證與原因。
  • CiteSwitch(cite-switch.jsx):可重用論文引用切換器,解析 BibTeX 推導 IEEE / APA 三式互換 + 一鍵複製。publications 頁用。
  • TerminalDemo(terminal-demo.jsx):可重用模擬終端機,逐行打字動畫 + mock 輸出 + play/step/reset 控制,行首 自動綠、 自動紅。commands=[{cmd, output}](output 為字串或行陣列)餵任意指令序列;無 props 時內建 CUDA 驗證流程(nvidia-smi → nvcc -V → gpu_test.py)。cuda-setup §4 已用,呈現「成功時每步該出現的輸出」。
每專案量身 map(gpustack 保留 ArchFlow):溫濕度=StaleValidator、Bitwarden=OptionPicker、R2=UploadDemo(batch 1);RustDesk/SAM2/Label Anything=OptionPicker 餵各自資料(版本比較 / 安裝路徑 / 推論後端)、乳牛跛行=LamenessGrades、Synology=CertDecision(batch 2,已完成)。原則:每頁挑最貼合其內容的互動模式,不全用同一個(OptionPicker 是刻意可重用的共用元件,餵不同資料即可;內容夠獨特才開新 bespoke);同理可延伸到 Notes(例如環境設定流程、版本相容矩陣、決策樹)。

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

  • 全站 meta 在 docs.json 頂層 description + seo.metatags(key-value)。seo.indexing: "all" 允許索引。
  • 逐頁 OG(現行做法):Mintlify 預設會用 site logo + 該頁 title/description + primary color 自動為每頁產 OG 圖。前提是 seo.metatags 不設 og:image/og:title/og:description(設了會壓掉逐頁,全站變同一張)。現況 seo.metatags 只留 og:type/og:site_name/og:locale/twitter:card/theme-color
  • 品牌底圖 + 主題thumbnails.background: "/images/og-background.png"(無文字暗底圖,留白給疊字)+ thumbnails.theme: "dark"(OG 卡明暗,全站單一選擇,非依瀏覽者切換 — OG 是爬蟲抓的靜態圖,無法 per-viewer;亮版需同步改兩個產生器與底圖回 cream)。
  • 首頁專屬卡index.mdx/en/index.mdx frontmatter 設 "og:image" 指向 images/og-cover.png(完整設計卡)。其他頁需專屬卡同法在該頁 frontmatter 覆寫(key 帶冒號要引號)。
  • og 圖產生器:scripts/og-cover.html(首頁完整卡)+ scripts/og-background.html(逐頁無文字底圖)+ scripts/og-logo.svg(共用 JM 標記)。流程:file:// 擋 svg → 先 python -m http.server <port> → Playwright navigate http://localhost:<port>/scripts/<檔>.html → resize 1200x630 → 等字型/圖 → 截圖 → 存對應 PNG。
  • 驗收:mint validate 綠驗 schema;逐頁自動卡只在 Mintlify 託管 build 時產生,本地 dev/validate 看不到,上線後用 opengraph.xyz / 各平台 OG debugger 抽驗疊字是否與底圖打架。完整機制與規範見 .claude/rules/og-cards.md

9. 常見任務 → 對應 skill 與 .claude/ 分工

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

.claude/ 目錄分工(沿官方慣例,2026-06-11 對齊)

依 Claude Code 官方 .claude 目錄結構(code.claude.com/docs/zh-TW/claude-directory)配置;各層職責固定,新增設定先查表再落點,不自創目錄名: 分層原則:AGENT.md 留鐵則與指標,機制細節住 rules/,流程住 skills/;互引不重複(單一事實來源)。歷史備註:rules/ 前身為自創的 roles/,那個位置 Claude Code 不會自動載入,2026-06-11 遷移正名。