昨天收在兩個數字上:代幣覆蓋率往上、硬編碼債往下,才算真的在收斂。當時留了一句沒展開的話——AI 產碼會放大硬編碼債,而 MCP 文件站成為新的分發介面。今天把這條線做完。問題很具體:當寫程式的主要消費者從人變成 AI agent,設計系統該怎麼被讀到。過去分發靠一個 npm 套件加一個文件站就夠,因為人會讀文件、會問同事、會在 code review 被抓;agent 三件都不做。它只用你餵進 context 的東西;讀不到的部分,它會生一個看起來很像的版本,那就是硬編碼債的來源。

📖 學

為什麼 AI 產的元件會繞過你的設計系統

不是模型不聽話,是它手上最強的先驗知識不是你的系統。訓練資料裡有幾百萬份 React 加 Tailwind 的範例,className="bg-blue-600 px-4 py-2 rounded-lg" 在統計上最自然;你的 <Button variant="primary"> 在整個網際網路上出現零次。要求模型「請用我們的設計系統」卻不給可讀的定義,等於要它猜一個沒見過的 API。Figma 官方文件講得很直白:MCP server 回傳的通常是 React 加 Tailwind,那是設計與行為的表述,不是最終的程式碼風格,得由你換成自己的代幣與元件。

三種失敗模式,嚴重度遞增。幻覺 API 寫出 <Button type="primary" size="large">,元件名對、prop 全錯,套的是 Ant Design 慣例。平行實作是需要 Modal 就從零手刻 divfixed 加 backdrop,你的 Dialog 沒被 import。值層洩漏最危險:元件用對、結構也對,但間距寫成 mt-[14px]、顏色寫成 #2563EB——畫面對、元件對,只有數字是硬的,它會平安通過 review。agent 產出量體大,這種債累積速度比人高一個量級,昨天的硬編碼債指標就是為了照出它。

Code Connect:把 Figma 元件釘到程式碼元件上

Figma MCP server(前稱 Dev Mode MCP Server)給 agent 的是結構化資料而非截圖:元件名稱與 variant、變數與樣式、圖層樹、節點渲染圖。agent 因此知道設計長什麼樣,卻不知道你的程式碼裡那顆按鈕叫什麼、從哪裡 import。

Code Connect 補的是這一段:把 repo 裡的元件對映到 Figma 檔案裡的元件。設好之後,MCP server 處理含有已連結元件的 frame 時,會在 context 裡生成 <CodeConnectSnippet> 包裝,內含設計屬性、import 語句、元件使用片段,以及你附加的自訂指示。差別就是 agent 拿到的是這個——

// 設好 Code Connect 後,agent 在 context 裡看到的
import { Button } from '@acme/ui'
<Button variant="primary" size="md">Continue</Button>

而不是一坨帶著寫死色值的 div——它把「該用哪個元件」從推測變成查表,是整套做法裡槓桿最高的一步。對映有兩種做法。UI 版在 Figma 介面裡設定,snippet 由設計元件名稱與當下屬性自動生成,非工程角色也能做。CLI 版把對映寫成 repo 裡的檔案並進版控,snippet 由你手寫——它能表達「prop 怎麼對映」與「檔案在哪」,正是 agent 最缺的兩件事。所以先廣後深:UI 連起最常用的一批,CLI 把核心元件寫細。Figma 的自訂指示欄位會以 user rules 形式併進 snippet,適合放 prop 慣例與無障礙要求。

llms.txt 與 MCP 文件伺服器

llms.txt 是放在網站上的 Markdown 檔,可放根目錄 /llms.txt 或任一子路徑——/docs/llms.txt 涵蓋 /docs/ 底下所有頁面,多份都適用時取最具體的。格式刻意極簡:H1 是唯一必填,接一段 blockquote 摘要,然後是若干 H2 底下的連結清單;慣例上有個 ## Optional 區塊,放 agent 在 context 吃緊時可以跳過的連結。v2 版另外建議同一個 URL 提供 .md 版本,並用 rel="alternate"rel="describedby" 兩個 link relation 讓客戶端找得到。

# Acme Design System
 
> React 元件庫與設計代幣。顏色、間距、字級一律走 token,禁止硬編碼。
 
- 元件一律從 `@acme/ui` import;代幣為 CSS 變數 `--acme-{category}-{role}-{scale}`
 
## Components
 
- [Button](https://ds.acme.com/components/button.md):variant、size 與禁用組合
- [Dialog](https://ds.acme.com/components/dialog.md):焦點管理與 aria 要求

MCP 文件伺服器是另一種東西。llms.txt 是靜態提示檔,發布出去,會找的客戶端才會找;MCP 是活的查詢介面,agent 用 tool call 來問,你決定回什麼、回多少。zeroheight 的遠端 MCP 走這條路:給一個 URL,下游自己接進 Cursor、Claude 或 Copilot,也能接 Figma Make、v0、Lovable,讓生成的原型用你真正的元件。想自己搭,langchain 的 mcpdoc 就是把一組 llms.txt 包成 fetch_docs 工具給 IDE 用。

llms.txtMCP 文件伺服器
控制權不知道誰讀了多少每次呼叫可稽核、可分權限
建置成本近乎零,平台多能自動生成要維運、要處理認證與速率
適合公開文件站、對外元件庫內部系統、需細控回傳量

選法很簡單:兩個都做,但先做 llms.txt。它成本幾乎為零,而且會逼你回答一個好問題——如果只能給 agent 二十條連結,你會給哪二十條。內部系統再加 MCP,因為內部文件通常不能公開,也需要按團隊分權。但 llms.txt 只是提案不是標準,多數對話型工具不會預設去找它,別當唯一防線。

規則檔要寫什麼才真的有效

AGENTS.mdCLAUDE.md、各家 IDE 的 rules 檔,本質都是每次請求都會被讀進去的常駐 context。這推出兩個結論:它有機會成本,每個 token 都在排擠任務本身的推理空間;寫太長還會降低遵循率,因為模型能穩定遵守的指令量有上限。所以規則檔不該寫文件,該寫約束與座標,四類最有效。可驗證的禁止句:「不要硬編碼顏色,一律使用 var(--acme-color-*)」比「請遵循設計系統規範」有用一百倍,因為前者能被 lint 檢查。路徑座標:代幣在哪個檔、元件在哪個目錄、新元件放哪;agent 找不到就自己造一個。替換規則:交代 Figma MCP 回傳的 Tailwind class 要換成專案代幣。流程順序:先取設計上下文、必要時先取節點總覽再取局部,接著取截圖,兩者都有才實作。

- IMPORTANT: 一律優先使用 `packages/ui` 底下的元件;找不到對應元件時停下來問,不要自行實作。
- 禁止硬編碼 hex、px、rem;顏色與間距一律使用 CSS 變數形式的設計代幣。
- 把 Figma MCP 回傳的 React + Tailwind 視為設計意圖的表述,不是最終程式碼風格。
- 新元件放在 `packages/ui/src/components/`;產品專屬元件不得放進此目錄。

不該放的:元件的完整 API、長篇設計原則、會過期的清單。規則檔是常駐成本,文件站是隨選成本,放錯位置代價差很多。

怎麼驗證有沒有用

最誘人的失敗是「裝好 MCP 就宣告勝利」。MCP、Code Connect、規則檔全是輸入不是結果,結果要用昨天的指標量,而且要分開量人寫的與 agent 寫的

硬編碼債密度 = 寫死的 hex / px 出現次數 ÷ 程式碼行數 × 1000
系統元件占比 = 設計系統元件實例數 ÷ 全部元件實例數

按 commit 來源切開,標記為 AI 協作的 PR 一組、其他一組。如果 agent 那組的密度顯著高於人的那組,結論是你的分發介面還沒生效,不是「AI 就是這樣」。措施上線前後各取兩週對照,只看總量會被程式碼行數的成長稀釋掉。另一個訊號是覆寫率:agent 產的程式碼裡有多少系統元件被額外塞了 classNamestyle。這個數字高,通常代表 Code Connect 的 snippet 沒寫出足夠的 prop 對映;它是需求清單,不是違規紀錄。

界線

最後這件事比所有工具都重要:agent 只會照它能機器讀到的東西做。只存在 Figma 註解裡的規範、只存在 Slack 討論裡的共識、只存在資深工程師腦中的慣例,對它而言等於不存在。agent 把這個老問題放大了,因為它不會停下來問,也不會露出困惑的表情,它會直接產出五百行看起來很合理的程式碼。

所以任何你希望被遵守的規範,都要有機器可讀的落點:命名慣例落在 lint 規則,禁用組合落在 TypeScript 型別,代幣約束落在 CI 的硬編碼債檢查,元件對映落在 Code Connect。文件是給人看的補充,不是規範的載體。反過來,一條規範如果找不到機器可讀的表達方式,通常代表它本身寫得不夠清楚。

🧠 記

  • AI 繞過設計系統不是不聽話,是訓練資料裡的 Tailwind 慣用寫法遠強於只存在私有 repo 的 API;不給可讀定義就等於要它猜。
  • 最該防的是值層洩漏:元件用對了但數值寫死,會平安通過 review,直接變成硬編碼債。
  • Code Connect 讓 agent 拿到 import 語句與真實使用片段;先用 UI 鋪廣度再用 CLI 寫深,但它只在從 Figma 節點出發時生效。
  • llms.txt 靜態、被動被讀;MCP 文件伺服器是活的查詢介面、可稽核可分權。先做前者,內部系統加後者。
  • 規則檔是常駐成本,只放可驗證的禁止句、路徑座標、替換規則、流程順序;API 留給文件站。
  • 裝好工具不是成果。把 AI 產出與人寫的分組比對硬編碼債密度與覆寫率,指標往下走才算。

✍️ 實踐

用 20 分鐘寫出設計系統的第一版 llms.txt,並立刻用盲測驗證它有沒有效。

  1. **先做取捨(5 分鐘)。**開一份空白清單,只准寫二十條連結,從最常被問、最常被寫錯的元件與代幣頁面挑起。爆表代表次要的該丟進 ## Optional
  2. **寫檔(6 分鐘)。**H1 是專案名,blockquote 講清楚「這是什麼、什麼一律禁止」,接著 ## Components## Tokens 放連結,每條補一句這頁能回答什麼問題。
  3. **加三條規則(4 分鐘)。**在 AGENTS.mdCLAUDE.md 補三行:元件從哪裡 import、禁止硬編碼 hex 與 px、Figma MCP 的 Tailwind 輸出要換成專案代幣。就三行。
  4. **盲測(5 分鐘)。**開乾淨的對話,只把 llms.txt 貼進去,要它做一顆「有 loading 狀態的主要按鈕」。檢查:有沒有 import 你的元件、prop 名稱對不對、有沒有寫死值。
  5. **記下基線。**跑 rg -o "#[0-9a-fA-F]{3,8}" src | wc -l,把數字與日期寫進昨天那張表,註明「已上線 llms.txt」。

自我檢查兩題:

  • 你 llms.txt 裡每條連結指向的頁面,是乾淨的 Markdown,還是要 agent 自己從導覽列與腳本裡剝內容?後者效果會打對折。
  • 把那三條規則刪掉,剛才的盲測結果會有差別嗎?沒差別代表規則沒生效,有差別才值得留在常駐 context 裡付 token。

🔗 延伸學習

💬 問 AI

1. 我的設計系統有 40 個元件,要開始做 Code Connect。請排出導入順序:哪些用
   UI 快速鋪、哪些值得用 CLI 手寫 snippet,判準是什麼。並說明哪一類元件
   (compound、polymorphic asChild、需要 provider 的)對映時最容易出錯。
 
2. 請為一個 React 設計系統文件站設計 llms.txt。前提:60 個頁面、context
   預算壓在 2000 token 以內。哪些頁面該進主清單、哪些丟 ## Optional、
   哪些根本不該列?請解釋每個取捨的理由。
 
3. 我要決定內部設計系統文件走 llms.txt 還是自建 MCP server。條件是:8 個
   下游團隊、部分文件含未公開的產品規劃、希望知道誰在查什麼。請做決策分析,
   包含維運成本、認證方式、混用時兩邊各放什麼。
 
4. 我要證明導入 Code Connect 與規則檔真的降低了硬編碼債。請設計量測方案:
   如何從 git 歷史區分 AI 協作與人工 commit、用什麼分母正規化以免被程式碼
   成長稀釋、哪些混淆因素會讓結論失真。