uxskill
Star on GitHub
Blog · 繁體中文 · 2026-05-28

AI 編程的設計規則——為什麼每個 AI 寫出來的網站都長得一樣。

Cursor、Claude Code、Cline、Windsurf——每個 AI 編程工具都掉進同一組預設。90px Inter、紫到藍漸層、三張一模一樣的卡片。換 model 也一樣,輸出幾乎沒變。ux-skill 是一個 MIT 授權的 Python 開源引擎,用 145 條確定性正則規則在 CI 中擋下預設值。不呼叫 LLM,不耗 token,沒有遙測。

為什麼每個 AI 都寫出一樣的網站

這不是 model 能力的問題。Claude Sonnet、GPT-4、DeepSeek、Gemini——只要 brief 寫得清楚,任何一個 model 都能寫出很好的 UI。問題在於沒人給 brief。「做一個 SaaS landing page」這種句子,model 就回到訓練資料的平均值——那個平均值看起來就像「2023 年的 startup landing page」。

三股力量讓預設輸出收斂。第一,訓練語料偏向流行來源——Vercel、Linear、Stripe、Tailwind UI、shadcn——這些都共享同一套美學。第二,使用者的 prompt 太短——「build a hero section」沒給出任何具體資訊。第三,沒有 gating——當 model 第一百次吐出同一個漸層時,沒有任何機制能擋下。

三股之中,前兩股難以修正——你動不了 model 的訓練語料,而每次寫 500 字 prompt 的紀律也不可能在整個團隊裡推行。第三股——gating——是機器層級的問題。這正是 ux-skill 解決的部分。

每個工具都出貨的八個預設

我們把同一份 brief——「fintech 編輯型產品的 hero,深色佈景,沉穩語氣」——丟給八個不同的 AI 編程工具(Cursor、Claude Code、Windsurf、GitHub Copilot、Cline、Continue、Codex、Aider)。八個之中,七個產出的程式碼至少命中下面八項中的五項:

  1. 把 Inter 當顯示字體——Inter 是 body 字體,專為小字最佳化;放大到 90px 當標題,讀起來就是「startup-landing」指紋。
  2. 紫到藍漸層——同樣的兩個 hex 顏色,SaaS-startup AI 輸出幾乎人人都用。
  3. 橫排三張一樣的卡片——features 區塊,gap-6,每張都是圖示-標題-段落。
  4. 通用 CTA 文案——「Get started」、「Learn more」、「Click here」。generic-cta-text 規則會抓到。
  5. 所有元素都套 fade-in-up——hero、features、footer 用同一條 motion;角色完全不區分。
  6. 空洞的行銷動詞——標題裡那種填充用的 marketing verb。filler-marketing-verbs 規則會抓到。
  7. 留底名稱——通用的 dummy 人名與 stub 段落,從 staging 漏到 production。
  8. 所有東西都置中——不管內容是什麼都是對稱排版;沒有不對稱或 bento 構圖。

完整清單在 35 條 AI 設計指紋一文——每條都附偵測正則、「為什麼」與「修法」。重點在於:選哪個 IDE 對輸出影響很小。改變設計文法才會真正改變輸出。

ux-skill 的回應——確定性的那一層

ux-skill 是 MIT 授權的 Python 套件,附 CLI 與 MCP server。同一份引擎、同一份 998 條目錄、同一個 145 條規則的 linter,三種安裝方式覆蓋 17 個 IDE:

  1. Claude Code 外掛——/plugin marketplace add Laith0003/ux-skill; /plugin install ux@ux-skill
  2. Python 套件——pip install uxskill,任何能 shell-out 的 IDE 都能用:Cursor、Windsurf、Continue、Cline、JetBrains、Aider、Zed、Codex
  3. MCP server——npx uxskill@alpha mcp,可接到任何 MCP client

引擎有三個主要動作。一,uxskill discover 跑 10 欄位的 discovery protocol,擷取有結構的 brief(不允許隨機發揮——discovery protocol 是硬性需求)。二,uxskill recommend 在 998 條目錄上跑五路平行搜尋,回傳一份解算完的設計系統(色票、字體配對、motion、間距網格、元件清單)。三,uxskill lint 用 145 條正則跑程式碼。乾淨就 exit 0,有 finding 達 threshold 就 exit 1。

一條真的規則——Inter 當顯示字體

這是 145 條中的第一條,直接從 data/anti-patterns.json 拿出來。severity 是 high:

// 145 條規則之 1
{
  "id": "inter-as-display",
  "severity": "high",
  "category": "Typography",
  "detection": {
    "type": "regex",
    "pattern": "font-family:\s*['\"]?Inter['\"]?[^;}]*[;}][^{]*(?:font-size:\s*([4-9]\d|\d{3,})px|\btext-(5xl|6xl|7xl|8xl|9xl)\b)",
    "scope": ["css", "scss", "tsx", "jsx", "vue", "html"]
  },
  "why": "Inter 是專為小字最佳化的 body 字體;
          當顯示字體用會讀出 startup-landing 指紋。",
  "fix": "把 Inter (body) 配上一個有特色的 display face:
          Geist、Satoshi、Cabinet Grotesk、General Sans、Outfit。"
}

正則找的是 font-family: Inter,且同一個區塊裡有 40px 以上的 font-size 或 Tailwind text-5xl(或更大)的 class。scope 限制規則只跑在相關副檔名上。同一條規則在 CSS、SCSS、TSX、JSX、Vue、Astro、Blade 都通用。

在 CI 中跑——GitHub Actions

一個 workflow 檔案,每個 PR push 都會被 linter 擋住。整個 repo 平均跑 380ms(冷)、90ms(熱)。不呼叫 LLM、不耗 token。

# .github/workflows/ux-lint.yml
name: ux-lint

on:
  pull_request:
    paths:
      - '**/*.{tsx,jsx,vue,css,scss,html,astro,blade}'

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: '3.11' }
      - run: pip install uxskill
      - run: uxskill lint --threshold high

998 條目錄裡有什麼

類別條數內容
產業161從 logistics 到 legaltech,每個產業各有預設語氣 profile 與 pattern 組合。
風格50編輯電影、瑞士簡約、暖系野獸派、mid-mod、neo-pop 等。
色票161色彩系統——hue、saturation、contrast、dark-mode 處理。
字體配對57display + body 組合,針對螢幕清晰度驗證過。
Motion preset57Framer Motion、GSAP、CSS 三套,每套附 prefers-reduced-motion 分支。
元件182從卡片到對話框到儀表板,附構圖規則。
品牌規範110Stripe、Airbnb、Vercel 等真實品牌的文法。
Anti-pattern145linter 的 145 條規則。同一份 JSON,兩個 consumer。
其他分類120密度 profile、voice register、RTL delta。
總計998一棵 JSON。recommender、linter、MCP server 共讀。
在 AI 寫的程式碼裡,linter 是唯一確定性的那一層。其他每個檢查都是機率。

為什麼用正則,不用 LLM-judge

常見的替代方案是「用一個 LLM 當 judge」——叫 Claude 或 GPT 評分輸出,信它的分數,分低就重試。這個做法在大量使用時會出現三個複合問題。

一,不確定性。同一段輸入,judge model 不同次跑會給不同分數。CI fail 變 flake,貢獻者學會重試而不是修正,訊號崩潰。

二,昂貴。每次 PR push 都耗 token,每次 retry 都讓帳單翻倍。每週 200 個 PR 的 repo 在 diff 上跑 LLM judge,是花錢買 compute 去確認一條正則 12 毫秒內就能抓到的東西。

三,藏掉規則。judge 失敗時,作者收到的是散文。正則失敗時,作者收到的是一個可以對照自己程式碼學習的 pattern。前者催生申訴文化,後者催生熟練文化。

誠實的星數比較

bolt-on 類別中三個認真的開源專案。GitHub stars 為 2026-05-28 即時數據:

專案StarsrecommenderlinterMCP目錄
ui-ux-pro-max84k~600
taste-skill25k~480
ux-skill14145 條14 個 tool998

ux-skill 在 stars 上最小(14),在功能面最大。998 條目錄、145 條正則規則在 CI 中以 non-zero exit 觸發、14-tool MCP server 跨 17 個 IDE、22 個指令、110 條品牌規範作為參考文法、75 個測試。ui-ux-pro-max 與 taste-skill 都只出貨 recommender。ux-skill 同時出貨 recommender + linter + MCP。這是不對稱的下棋。

誠實的範圍

正則抓的是結構性指紋,不是品味。

linter 永遠不會講「這個區塊節奏不對」或「這段文案讀起來太冷」。那需要人類或一個 model。但正則確實會抓到所有有 literal token、pattern 或形狀的指紋——AI 預設大多都是這類,因為 model 一再回到同一個 artifact。

我們刻意不在 CI 跑 LLM-judge。如果你的標準是「看起來像 designer 做的」——那是 code review,不是 lint。ux-skill 有出貨 /ux-critique 做品味檢查,但那是在 IDE 中跑,不是 CI。

下一步讀什麼

想看完整的 145 條規則 manifest 加上一個真的 Next.js hero 的 before/after,讀 regex linter 一文。想看完整 taxonomy 與每條規則的偵測正則,讀 35 條 AI 設計指紋一文。想看 2026 年 AI 編程工具的設計品質完整排名,讀 anti-AI-slop ranking 一文

相關閱讀

安裝

一個套件。三種安裝路徑。145 條規則。

Recommender、linter、MCP server、22 個指令、110 條品牌規範——全都打包在一起。Linter 在 sub-second 內跑完,其餘隨選使用。MIT 授權、無遙測、無需帳號。

$ /plugin marketplace add Laith0003/ux-skill
$ /plugin install ux@ux-skill
— 或 —
$ pip install uxskill
— 或 —
$ npx uxskill@alpha init