Communitygithub.com

rinkledink/design-by-story

當使用者想要一個可點擊的產品原型或設計模型(網頁應用程式、手機應用程式、平板應用程式,或一次包含多個),並希望按使用者故事組織時使用。它會建立一個自包含的 HTML 檔案,內含裝置切換器(網站 / Android / iPhone / iPad)和故事切換器,讓審查者可以選擇一個故事,並逐步瀏覽該故事在每種裝置上所需的畫面與資料,同時附帶驗收條件、優先級、狀態和備註。此外,在新增、變更或拆分這類原型中的故事時也可使用。

design-by-story 是什麼?

這個技能「Design by Story」(按故事設計)讓 AI 代理能夠建立一個單一的 HTML 檔案,作為全功能、可按故事瀏覽的產品原型。它與 Claude Code、Cursor 或其他具備檔案系統和瀏覽器存取能力的 AI 代理工具相容,可將使用者的輸入(例如產品描述、使用者故事列表、所需裝置)轉換為一個內建裝置框架(網站、Android、iPhone、iPad)和故事選擇器的互動式模型。原型會將所有內容整合在一個檔案中,無需建置步驟或後端,並以精確的驗收條件、優先級(MoSCoW)、狀態、逐步演練腳本和備註來組織每個使用者故事。對於需要根據使用者故事和裝置來視覺化、審查及疊代產品功能的產品經理、設計師和開發團隊來說,這項技能特別實用。在背後,AI 會先收集資訊,根據品質檢查清單驗證故事,規劃每個故事的畫面與種子資料,再產生包含內嵌 CSS/JS 的 HTML 檔案。它支援變更、合併和拆分故事,同時維護跨裝置的狀態一致性,是敏捷產品開發工作流程中一個功能強大的協作原型製作工具。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/rinkledink/design-by-story-skill/tree/HEAD/design-by-story

在你喜歡的 AI 中提問

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

說明文件

Design by Story

建立一個單一檔案的 HTML 產品原型,可在多種裝置上檢視,並按照使用者故事來劃分,就像按照裝置劃分一樣。

頂部欄有兩個切換器:

  • 裝置:例如 網站 · Android · iPhone。相同的產品,不同的框架。
  • 故事:「所有故事」加上每個使用者故事一個條目。選取一個故事會將共用資料重設為該故事的種子資料,將每個裝置帶到該故事的起始畫面,並開啟一個面板,顯示該故事、優先級、狀態、驗收條件、逐步演練和備註。

兩個選項都位於 URL 的 hash 中(#story=S2&device=iphone),因此可以將某個裝置上某個故事的連結貼到審查或工單中。

工作流程

  1. 收集輸入(僅在一次訊息中詢問缺少的項目):

    • 產品是什麼以及誰在使用它。
    • 要顯示哪些裝置。預設值:網站 + Android + iPhone。如果是現場/自助服務機用途,則加入平板。
    • 使用者故事,可以是任何形式(列表、待辦事項清單匯出、功能文件)。
    • 驗收條件格式: Given/When/Then,還是簡單規則?預設為 Given/When/Then。
    • 優先級(MoSCoW)和狀態,如果他們有的話。否則預設為 should / draft。
    • 主要資料模型(主要記錄 + 關鍵欄位),或者從故事中推斷出來。

    將每個故事正規化為故事格式。如果使用者沒有故事,則從產品描述中草擬 3-6 個,並在建立前與他們確認。

  2. 檢查故事是否符合品質檢查清單。用一個簡短的列表來提出問題。不要無聲地改寫使用者的措辭。

  3. 規劃每個故事的畫面。 對於每個故事,列出它在每種裝置上觸及的畫面以及所需的種子資料。只有在產品真的以那種方式工作時(例如管理員僅在網站上),故事才會跳過某個裝置。它的 devices 列表會說明這一點,並且在選取該故事時,切換器會停用其他裝置。

  4. 複製 assets/shell.html 到使用者選擇的路徑(預設為 docs/reference/prototype.html)並填入內容。閱讀 references/prototype-spec.md 以了解視覺規則(框架、標記、字型、卡片、藥丸、提示、抽屜、圖示、文案語調)。

  5. 建立畫面,而不是故事。 畫面是共用的;故事是入口點和種子資料。永遠不要為每個故事複製一個畫面。如果一個故事需要一個變體,則從種子資料驅動它。

  6. 在瀏覽器中驗證。 如果你有瀏覽器工具,請使用它。否則使用無頭 Chrome:--dump-dom "file://…/prototype.html#story=S2&device=iphone" 來檢查渲染的內容,--screenshot 來查看它,以及 --enable-logging=stderr 來捕獲主控台錯誤。檢查:

    • 每個故事在其列出的每種裝置上是否都開啟在正確的畫面;
    • 每個驗收條件是否都可以展示,並且可以點擊逐步演練;
    • 在故事中切換裝置時是否保持狀態;
    • 沒有故事的控件出現在另一個故事之下,並且「所有故事」中每個故事的控件都能共同運作;
    • 主控台是乾淨的。
  7. 保持同步。 當稍後新增或變更故事時,在同一編輯中更新其 #story-text 條目、BEHAVIOUR 條目以及它列出的每個裝置。

故事格式

一個故事存在於 shell 中的兩個位置,都由其 id 索引:

  • 其文字在 #story-text JSON 區塊中,在故事面板中以唯讀方式顯示;
  • 其行為在 BEHAVIOUR 中,這只是程式碼。
<script type="application/json" id="story-text">
{
  "S1": {
    "title": "儲存搜尋",
    "story": "身為訪客,我可以儲存搜尋,以便在無需再次搜尋的情況下收到關於新配對的通知。",
    "priority": "must",
    "status": "draft",
    "ac": [
      { "id": "S1-AC1", "text": "Given 我搜尋了 \"橡木桌\",when 我點選儲存搜尋,then 它會出現在已儲存項目下" },
      { "id": "S1-AC2", "text": "Given 該搜尋已經儲存,when 我再次儲存它,then 已儲存項目仍然只顯示一次" }
    ],
    "acNext": 2,
    "walkthrough": ["搜尋 \"橡木桌\"", "點選儲存搜尋", "開啟已儲存項目"],
    "outOfScope": ["電子郵件提醒"],
    "assumptions": ["訪客必須登入才能儲存"],
    "questions": ["已儲存搜尋是否有數量限制?"]
  }
}
</script>
const BEHAVIOUR = {
  S1: {
    devices: ['web', 'android', 'iphone'],         // 此故事適用的框架
    start: { web: 'search', android: 'search', iphone: 'search' }, // 每個裝置的畫面
    features: ['save-search'],                      // 此故事切換的功能
    seed: () => ({ user: SIGNED_IN, saved: [] }),  // 此故事的新鮮資料
  },
};
欄位規則
story身為 <角色>,我可以 <動作>,以便 <效益>. 效益是使用者獲得的東西,不是動作的重新陳述。
prioritymust · should · could · won't (MoSCoW)。
statusdraft · in review · agreed。
ac物件 { id, text }。ID 為 <故事>-AC<n>,永不重新編號,永不重複使用。請參閱下文。
acNext此故事曾發出的最高 AC 編號。新的 AC 使用 acNext + 1,並且 acNext 會更新以匹配。每當你新增 AC 時都要更新它。
walkthrough審查者點擊瀏覽的示範腳本。不是驗收條件;保持簡短。
outOfScope, assumptions, questions純文字列表。寧可留空也不要編造填充物。將使用者不確定的任何內容記錄為問題。

seed() 在每次呼叫時都回傳一個新鮮的物件,因此重新選擇一個故事總會重新乾淨地啟動它。「所有故事」使用 DEFAULT_SEED 和每個裝置的首頁。

驗收條件

  • 每個 AC 一個可測試的行為,採用使用者選擇的格式。Given/When/Then 一行完成:Given <上下文>, when <動作>, then <可觀察的結果>。
  • 精確的文案: 當 AC 是關於一則訊息時,引用該訊息(then 我看到「目前沒有開啟的項目。」),永遠不要寫「一條友善的訊息」。
  • 結果,而非樣式: 「它顯示為已完成」,而不是「一個綠色藥丸出現」。只有當視覺細節就是需求時,它才是一個 AC。
  • 在一個裝置上可測試。 不要撰寫關於其他裝置的 AC(「出現在每個裝置上」、「僅限網站」、「手機無法更改」)。一個故事涵蓋哪些裝置屬於 devices,而裝置之間的同步是後端的責任。
  • ID 是永久的。 S1-AC3 在編輯、移動或拆分到子故事時保留其 ID,以便可以追溯到測試和工單。新的 AC 使用 acNext + 1。已刪除的 ID 不會再次發出,也不會重新編號。

品質檢查清單

在建立每個故事之前,以及每次它發生變化時進行檢查:

  • 角色是否是真正的使用者角色,並且效益是否是他們會說的話?
  • 它是否獨立交付價值,並且是否足夠小以在一分鐘內演示?如果不是,拆分它。
  • 每個 AC 是否都有 ID、單一行為和可觀察的結果?
  • 空值、錯誤和限制情況是否都已涵蓋,或列在 questions 下?
  • 對其他故事的依賴關係是否可見?(一個共用的功能鍵,加上 assumptions 中的提及,例如「基於 S2 構建」。)

故事功能在其故事被選取之前是關閉的

每個故事引入的互動都有一個功能鍵,列在該故事的 features 中。can('save-search') 只有在選擇了列出它的故事時才為 true。

  • 渲染: 將故事的控件包裹在 can(...) 中,這樣它們就不存在(沒有按鈕、沒有表單、沒有選單項目)。不要將它們顯示為禁用狀態。審查者應該只看到所選故事新增的內容。
  • 處理器: 每個故事處理器以 if (!can('save-search')) return; 開頭,這樣在故事之外什麼都不會觸發,即使是來自過時的 DOM 或主控台。
  • 「所有故事」 會同時開啟每個故事的功能:整個產品的當前樣貌,使用 DEFAULT_SEED。檢查故事是否在那裡發生衝突(例如,兩個控件在同一個位置)。
  • 依賴另一個故事互動的故事會列出兩個鍵(例如「按狀態篩選」列出 ['filter', 'complete'],這樣就可以顯示勾選任務會如何影響篩選後的列表)。
  • 故事僅顯示的資料(例如受指派者的姓名縮寫)不受限制;只有更改它的能力才受限制。

變更故事

原型僅顯示故事;它永遠不會編輯或儲存故事。所有的故事更改都透過 Claude 在聊天中進行:

  • 新故事: 草擬故事、AC 和問題,與使用者一起執行品質檢查清單,然後在一個編輯中寫入 #story-text 條目和 BEHAVIOUR 條目並建立畫面。一個故事永遠不會只作為文字存在。如果它只是文字存在,shell 會將其排除在切換器之外,並在主控台中記錄一個錯誤。
  • 已變更的故事(措辭、AC、優先級、狀態、備註):編輯 #story-text。如果更改改變了故事的功能(新的 AC、不同的逐步演練),請在同一編輯中更新畫面和 BEHAVIOUR 以匹配。
  • 審查回饋: 當使用者轉達審查者的評論時,將每個評論轉換為上述變更之一,如果仍然懸而未決,則轉換為 questions 下的一個條目。
  • 總是說明你建立或更改了什麼,按故事和 AC ID 來區分。

如果使用者將故事保留在追蹤器(Jira 或類似工具)中,則該追蹤器是主副本。在此處鏡像其措辭,而不是僅在原型中編輯故事。

拆分故事

當使用者要求拆分一個故事,或者一個故事有大約 5 個以上的 AC、超過一個主要功能鍵,或者有可以單獨交付的 AC 時,將其拆分。

  1. 選擇一個拆分模式並說明你使用了哪一種:

    • 工作流程步驟(建立 → 審查 → 發布)
    • 操作(新增 / 編輯 / 刪除)
    • 先快樂路徑,然後邊緣情況(空值、重複、達到限制)
    • 按裝置或角色(手機擷取 vs. 網站管理)
    • 按資料變化(一個項目 → 許多,一種貨幣 → 幾種)
    • 先簡單,然後附加功能(普通排序 → 已儲存的排序偏好)

    每個子故事仍然必須是一個完整的 身為 <角色>,我可以 <動作>,以便 <效益>,並且有其自身的價值。

  2. 從父故事開始編號子故事: S3 → S3.1, S3.2, … 從 #story-text 和 BEHAVIOUR 中移除父故事,並將子故事放在原來的位置。shell 的 readHash 會將舊的 #story=S3 連結發送到 S3.1,因此共享連結可以繼續運作。

  3. 劃分,不要重複:

    • 驗收條件。 每個父故事的 AC 都移動到恰好一個子故事中,並保留其原始 ID(S3-AC2 在 S3.1 內部保持為 S3-AC2)。如果一個 AC 跨越兩個子故事,將它重寫為兩個新的 AC(S3.1-AC1, S3.2-AC1),並註明它們取代了哪個父故事 ID。
    • 功能鍵。 如果一個鍵的互動被拆分,則拆分它(filter → filter-status, filter-counts)。一個子故事也可能列出其兄弟故事的功能鍵,當它基於該功能鍵構建時,如上述依賴規則所述。
    • 裝置。 每個子故事只列出它真正觸及的裝置。
    • 種子資料。 後續子故事的 seed() 從較早子故事會留下的狀態開始(例如 S3.2 種子資料已儲存了某些項目),這樣每個子故事都可以獨立審查。
    • 備註。 為每個子故事提供適用於它的範圍外項目、假設和問題。除非使用者另有說明,否則子故事繼承父故事的優先級。
  4. 更新畫面: 對任何移動到不同鍵的控件重新設限。然後,在其列出的每種裝置上檢查每個子故事,並檢查父故事的 id 是否重定向。

  5. 將拆分報告為一個簡短的表格(子故事 id、故事、優先級、裝置、AC ID),以便使用者可以檢查每個父故事的 AC 是否都落到了某個地方。如果使用者在那裡保留故事,請在他們的待辦事項或功能文件中鏡像此拆分。

規則

  • 一個 HTML 檔案,內嵌 CSS/JS,無建置步驟,無框架,無後端。直接從磁碟開啟。
  • 所有資料在一個共用的記憶體中 state;每個裝置讀取和寫入它。
  • 渲染函數接受裝置 id 並從 state 重新繪製(參見 shell)。
  • 使用虛構的、中立的範例資料。永遠不要將其他專案中的名稱、品牌或內容複製到原型中。
  • 行動框架渲染相同的應用程式標記;Android 和 iPhone 之間的差異是瀏覽器裝飾(狀態列、瀏海/動態島、手勢條),而不是不同的應用程式,除非使用者要求特定平台的 UI。

相關技能