Communitygithub.com

mikeozornin/skills

當使用者要求互動式或可點擊的 HTML 原型、模型或產品 UI 流程、畫面狀態或功能審查時使用。

skills 是什麼?

這項技能專為在 Claude Code、Cursor 或 Codex 等 AI 代理開發環境中,快速建立互動式 HTML 原型而設計。其核心功能是將一個自包含的 HTML 檔案作為原型模板,代理只需撰寫其中的 JavaScript 和 CSS 部分,而無需重構整個模板的殼層(包括標頭、瀏覽器框架、狀態切換器、備註面板、畫面地圖等)。該技能強調先設計再編碼,要求代理在撰寫程式碼前,先透過一系列步驟(收集脈絡、定義問題、撰寫情境、與作者確認、設定深度)來確保原型聚焦於一個特定的決策問題。支援多狀態、多分支、多變體(最多 5 個),並可處理邊界案例(如錯誤、空狀態、權限不足等)。最終產出可直接運作的原型 HTML 檔案,並內建驗證機制(`protoCheck()`)來確保所有路徑可執行、無渲染錯誤。

相容平台✓Claude Code✓Codex CLI✓Cursor✓Windsurf
npx skills add https://github.com/mikeozornin/skills/tree/HEAD/skills/mo-build-html-prototype

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

建立 HTML 原型

每個原型都在此技能目錄的 assets/template.html 中建立:一個自包含的 HTML 檔案。模板已包含完整的殼層:標頭、瀏覽器框架、狀態切換器、備註面板、畫面地圖、審查者評論、帶有 k-* 元件的 Koobiq 權杖以及執行環境。殼層的 UI 語言為英文或俄文(根據作業系統/瀏覽器語言自動選擇);原型本身的內容則使用您撰寫的語言。您只需要撰寫 PROTOTYPE 區塊(JS)和章節 5. PROTOTYPE STYLES(CSS)。請勿破壞模板:切勿重建、重新設定樣式或描述殼層。

設計先於程式碼

原型是用於解決一個決策的工具,而非螢幕畫廊。在撰寫 prototype.js 之前,請依序完成以下步驟。

  1. 收集脈絡。 使用者是誰(角色、專業知識)、他們正在執行什麼工作、觸發該工作的原因,以及「完成」對他們而言是什麼樣子。如果產品已存在(儲存庫、螢幕截圖、Figma、文件或先前的原型),請沿用其導覽、術語、實體和資料,並僅設計變更的部分。請勿圍繞功能憑空發明一個產品。

  2. 定義問題。 用一句話(若原型較大,可用數句)說明審查者需要決定的事項,或 UI 中最值得懷疑的部分(使用者是否會找到 X、了解 Y、Z 是否與真實資料相符)。對於每個問題,請記錄審查者需要看到什麼才能回答,以及哪些狀態或資料可能破壞設計。如果請求中未指定問題,則將風險最高的決策作為問題,並在步驟 4 中提供給作者。

  3. 撰寫情境,使用使用者的語言,從觸發到結果:「分析師看到峰值 → 開啟規則 → 降低臨界值 → 查看將產生多少事件」。然後僅添加問題所需的分支:取消、驗證錯誤、空白或首次使用,以及那些尚未被發現需求但可能出現的困難情況:無權限、與其他物件衝突、限制、大量資料、物件目前狀態不允許的操作。步驟成為 STEPS,分支成為狀態,跨領域條件(角色、功能標誌、資料量)成為 SWITCHES。

  4. 在建立之前與作者確認。在一則簡短的訊息中,發送:

    • 問題;
    • 您計劃展示的情境及其分支和困難情況;
    • 您猜測而非從請求或產品中取得的所有內容,以編號列表形式列出,每項一個陳述句,以便作者能透過編號回覆:「2 — 不,需要經理核准」。

    等待回覆。如果只是對現有原型進行小幅修改,可跳過此步驟。如果作者要求不要提問,則根據您的猜測進行建置,並在回覆中列出這些猜測。

  5. 設定深度,針對每個步驟 × 狀態的組合:

    • 完整 = 在問題路徑上:可點擊、每個狀態、壓力資料;
    • 合理 = 上下文:靜態但真實;
    • 不包含 = 在回覆中指名不涵蓋的項目。

    僅使用問題所需的狀態:理想、空白或首次使用、部分、錯誤、無權限,每個步驟最多約 6 個狀態。僅在顯示特定內容(長時間操作、進度、部分結果)時才加入載入狀態。載入失敗通常不值得建立一個狀態,但「在此物件的狀態下不允許」通常值得。切勿偽造未經設計的結果。

  6. 先用文字設計每個畫面: 用一句話說明其目的、一個主要操作,以及使用者在這裡需要看到什麼才能做出決定,依重要性排序。然後使用標準的 Koobiq 模式(表格、表單、側邊面板、模態視窗、空白狀態)來建立。僅在問題所在之處引入新穎元素;其他部分看起來應與產品的一般畫面相同。

    • 每個操作都有可見的結果:發生了什麼事,以及物件現在在哪裡。
    • 破壞性操作應指明物件名稱和後果。按鈕通常顯示動詞。
    • 錯誤應說明如何修正,並保留輸入內容。
    • 跨畫面、麵包屑、通知訊息和 URL 使用統一的名稱。UI 文案應使用使用者的語言,如果已安裝 ux-write 規則,則應遵循。
  7. 在建立檢視之前先撰寫資料。 使用能測試版面配置的真實領域資料:一個長名稱、0 / 1 / 多個計數、一個罕見狀態。使用固定的日期和值(不要使用 Date.now() / Math.random()),且不要使用 lorem ipsum。

變體,僅在問題為「哪個解決方案」時使用。在 VARIANTS 中建立 2-3 個(最多 5 個),而不是為審查者選擇。

  • 它們在結構(版面配置、層級結構、主要操作)上有所不同,而非顏色或文案。如果兩個草稿看起來相似,請重新製作其中一個,並明確禁止某些模式(「不要使用卡片網格」)。
  • 變體可以共享資料,但絕不能共享版面配置。
  • 為每個變體提供一個 title 和一行說明的 text。
  • 最佳回饋格式為「標頭用 B 的,列表用 C 的」。

完成條件

在回覆之前,請針對每個項目檢查原型:

  • 每個展示的路徑都從頭到尾可執行。 它從使用者遇到觸發點的地方開始,而不是從登入頁面或儀表板開始。每個展示的分支都有終點,回到路徑上或到達一個結果。移交給其他產品或系統時,應使用一個具有可見結果的存根(例如通知訊息,或「已在 Jira 中建立任務」等狀態),而不是複製其他 UI。次要控制項可以無作用(選單項目可以僅執行 close),只要沒有任何情境從該控制項開始。
  • 有爭議的部分已標記。 每個變更或有爭議的元素都有一個備註。當問題是要採用哪個解決方案時,應有 2-3 個結構不同的變體。
  • 沒有多餘的內容。 每個狀態、切換開關和備註都必須有助於回答問題或測試關於需求的猜測。移除其餘內容。

建置

  1. 取得可編輯的部分。 使用 SKILL_DIR = 此技能的目錄,A=$SKILL_DIR/scripts/assemble.mjs(使用 node 執行,無相依性),工作目錄例如 /tmp/proto-<name>/:

    • 新原型:node $A --split $SKILL_DIR/assets/template.html /tmp/proto-<name>;
    • 修改現有原型:node $A --split <file>.html /tmp/proto-<name>。重新組合也會升級其殼層。

    這會產生 prototype.js(示範 PROTOTYPE 區塊)和 prototype.css(第 5 節)。

  2. 改寫 prototype.js,取代所有示範內容:PROTO、STEPS、SWITCHES、S、NOTES、LINKS(通常為 [])、資料、VIEWS、ACTIONS。自訂 CSS 移至 prototype.css。分輪次進行:

    1. 主路徑,可點擊的端到端流程,處於理想狀態;
    2. 其他狀態和分支;
    3. 備註;
    4. 驗證並檢查完成條件。

    在路徑可運作之前,請勿對畫面進行潤飾。

  3. 組合: node $A <target>.html /tmp/proto-<name>/prototype.js /tmp/proto-<name>/prototype.css。它會檢查語法和必要的宣告。僅交付 HTML 檔案。

  4. 檢視: 每個步驟一個 VIEWS[step](S),回傳一個 HTML 字串,並根據 S.state / S.sw 進行分支。使用 k-* 類別建置;請參閱 references/koobiq-cheatsheet.md。

    • 每個狀態在直接開啟時都應完整渲染。 直接開啟(彈出視窗、雜湊連結、地圖縮圖、備註、←/→、protoCheck)從初始的 S 加上該狀態的 seed 開始,例如 { id: 'confirm', title: 'Confirmation', seed: { name: 'Brute force: RDP' } }。流程中的 goto() 會保留使用者輸入的內容。VIEWS 只讀取 S 和常數資料。
    • 覆蓋層。 模態視窗或側邊面板會繪製在它所覆蓋的畫面上方,位於同一個檢視內。一次性覆蓋層(例如確認對話框)是該步驟的一個狀態(form/confirm)。具有自己子流程的覆蓋層(表單 → 錯誤 → 確認)可以作為自己的步驟,並在下方繪製被覆蓋的畫面。若要在面板上方顯示模態視窗,請在面板之後渲染模態視窗:最後一個 .k-overlay 是最上層的,且只有它的標記會顯示。
    • 捲動。 比瀏覽器框架高的畫面應在框架內捲動,就像一個頁面。新的步驟從頂部開始;同一步驟的新狀態或變體則保持捲動位置,以便審查者在相同位置進行比較。應用程式殼層(.app-body + .app-content)應在 .app-content 內捲動,與之前相同。
    • 使用 data-act → ACTIONS 繫結點擊事件。僅透過 goto(step, state) / data-goto 切換畫面,以便狀態按鈕、網址列和雜湊保持同步。
  5. 備註(3-7 則) 僅放在問題所涉及的元素上:已變更或有爭議的元素。

    • 在元素上加上 class="changed" data-anchor="note-N",並在元素內部放入 ${marker(N)}。將無效或停用的元素包在 <span class="k-anchor changed" data-anchor="note-N"> 中。
    • 備註 text 用 1-2 句話說明變更內容及其原因。如果是假設,請以「檢查:…」結尾。
    • try 說明要點擊什麼來查看它。
  6. 畫面地圖 會根據狀態和轉換自動建立。轉換來自每個狀態的標記:data-goto,以及其啟用的控制項、選單項目和最上層覆蓋層所呼叫的 ACTIONS 中的文字 goto() / openState() 呼叫(停用的控制項不會產生箭頭)。如果在同一個動作中計算出一個狀態,只要該狀態的可能 ID 以字串形式出現:goto('list', S.q ? 'empty' : 'data')。透過輔助函式、計時器或使用者未點擊的事件進行的轉換,應放到 LINKS 中:{ from: 'report/building', to: 'report/ready', label: 'Report ready' }。

  7. 驗證(請參閱驗證)。修正並重新組合,直到 protoCheck() 通過,然後根據「完成條件」檢查原型。

  8. 回覆,包含檔案路徑、步驟 × 狀態表格、刻意不涵蓋的內容,以及在確認後所做的任何猜測。請勿描述殼層。

審查者評論

使用者可能會貼上「複製全部」動作產生的 Markdown。它會在 File: 行中標示檔案名稱。每個 ## 是一個帶有其雜湊(#step/state?switches)的畫面;若有變體,則以 Variant B · Cards → 開頭,且雜湊中包含 variant=<id>。殼層會以審查者的 UI 語言撰寫,因此可能是俄文:Файл:、Вариант B。每個 ### 是一個元素,包含其在 #view 內的選擇器、其 data-* 屬性以及連結的備註編號,後面接著以引文形式呈現的評論。

要套用評論,請在該檔案(該變體)的 VIEWS[step] / ACTIONS 中找到該元素,然後透過 --split 編輯,並重新組合到同一個檔案中:評論儲存在瀏覽器的 localStorage 中,鍵值為檔案路徑。

殼層規則

  • 標頭 = 僅短標題。 框架上方不得有任何副標題、說明、圖例或「...流程的原型」等文字。
  • 一個狀態控制項:「步驟 · 狀態」彈出視窗。不得有上一步/下一步步驟器、每個畫面的分段控制項、框架上方的標籤或自訂快速鍵(←/→、Esc 和內建的 1-9 變體選擇器除外)。
  • 備註僅位於 aside#notes 中,在 .browser 之外。 在 .app 內部僅有編號標記。切勿在 ::after 工具提示、覆蓋層或應用程式內部的「審查模式」欄中放置備註文字。
  • 請勿編輯 RUNTIME,也請勿移動或重新設定 deck、stage、browser、notes、comments 或 screen map 的樣式。行為應寫在 ACTIONS 中。
  • 預設使用 Koobiq: k-* 類別和 --kbq-* 權杖。不得使用自訂的十六進位/rgb 顏色、自調色盤(--bg、紫色強調色)或僅限淺色模式的樣式,因為主題切換功能必須能運作。如果使用其他設計系統,請保留殼層,僅重新設定應用程式的樣式。
  • 單一檔案,無外部 JS。

PROTOTYPE API

項目說明
標題 / 網址列PROTO.title、PROTO.url(S)
彈出視窗網格STEPS[{id,title,states[{id,title,seed?}]}]、SWITCHES[{id,title,options}]
狀態S.step、S.state、S.sw[id]、S.menu(已開啟的選單 id),加上您自己的欄位
導覽在流程中使用 goto(step, state, patch?)(保留 S);標記使用 data-act="goto" data-goto="form/errors"。openState(step, state) = 直接開啟(初始 S + seed)
動作data-act="name" → ACTIONS.name(el, e);除非回傳 false,否則會重新渲染
內建動作goto;close(S.menu = null);menu + data-menu="id"(切換);set + data-field + data-value(寫入 S,關閉選單)。選單也會在按下 Esc、外部點擊及任何其他動作時關閉
輸入data-model="field" 會寫入 S.field;data-live 會在輸入時重新渲染(保留焦點和游標位置);data-live="act" 會先呼叫 ACTIONS.act;data-scroll="key" 會保持捲動位置
焦點goto('form', 'errors', { focus: 'name' }) 會一次性聚焦於 [data-model="name"] 元素
輔助函式icon('search')、marker(n, '--x:100%;--y:50%')、tip(html, text, 'k-float--right')、matches(S.q, ...fields)、toast(title, {kind, text})、esc(str)
備註NOTES[{id, step, state, title, text(html), try}]:step/state 表示錨點所在位置
畫面地圖自動建立;LINKS[{from: 'step/state', to: 'step/state', label}] 用於新增掃描無法偵測到的轉換
變體VARIANTS[{id, title, text, STEPS?, NOTES?, VIEWS?, ACTIONS?, LINKS?, S?, url?}]。全域宣告為變體 A;變體僅覆蓋有差異的部分(S 會與全域 S 合併)。每個變體有自己的畫面地圖、備註和評論;SWITCHES 和上一步/下一步是共享的。選擇器位於標頭,按鍵 1-9

驗證

在背景啟動伺服器(file:// 通常會被封鎖),並在瀏覽器工具中開啟顯示的 URL 加上 <file>.html。每次重新組合後重新載入,因為僅雜湊變更不會重新載入檔案。

cd <dir> && node -e "const fs=require('fs'),T={'.html':'text/html; charset=utf-8','.js':'text/javascript','.css':'text/css','.svg':'image/svg+xml'};require('http').createServer((q,r)=>{const p='.'+decodeURIComponent(new URL(q.url,'http://x').pathname);fs.readFile(p,(e,d)=>{r.writeHead(e?404:200,{'Content-Type':T[require('path').extname(p)]||'application/octet-stream'});r.end(e?'Not found':d)})}).listen(0,'127.0.0.1',function(){console.log('http://127.0.0.1:'+this.address().port+'/')})"
  1. 在頁面中執行 protoCheck()(在控制台或瀏覽器工具的 evaluate 中),視窗寬度至少為 1440。它必須回傳 ok: true。它會開啟每個步驟 × 狀態 × 切換開關的組合(在兩種主題下),並報告渲染錯誤、空白畫面、溢出、損壞的標記或備註、未知的 data-act / data-goto / goto() / LINKS 目標、硬編碼的顏色以及模板殘留。修復每個警告(相同的狀態、無效的切換開關、非確定性資料、3-7 則以外的備註、未與其他步驟連接的步驟),或在回覆中解釋原因。
  2. 以 1440 以上的寬度目視檢查,並測試常見的邊界案例。使用隨附的瀏覽器工具面板以可控制的資料開啟每個狀態。
  3. 檢查「完成條件」列表。

相關技能