旅程示範 是做什麼的?
撰寫一個旅程、測試它、剪輯它。Claude 在 Chrome 中執行使用者旅程,將每個畫面儲存為凍結的 HTML 頁面,將這些幀佈局在一個故事板上,讓使用者在瀏覽器中編輯,並僅在他們批准後才使用 HyperFrames 渲染出 MP4。沒有任何螢幕錄製,因此任何畫面中的文字都可以在稍後變更,而無需重新執行旅程。
事實來源: 示範資料夾中的 STORYBOARD.md + snapshots/*.html。其他所有內容都是生成的。
需求
- 安裝了 Claude in Chrome 擴充功能的 Chrome(用於執行旅程和擷取)
- Node 18+,以及
npx hyperframes(靜態畫面與渲染;無需安裝步驟) - 此技能的腳本:
scripts/freeze.js(擷取)、scripts/demo.mjs(建置與可編輯看板)。 透過路徑執行它們:node <此技能>/scripts/demo.mjs …
示範資料夾
位於使用者的儲存庫中 docs/demos/<slug>/,除非他們指定其他位置:
STORYBOARD.md 計畫:幀、說明文字、點擊、時間、備註 (編輯)
snapshots/*.html 已擷取的畫面 (僅編輯文字)
index.html scenes/ boards/ .build/ 由 demo.mjs 生成 (絕不編輯)
out/<slug>.mp4 渲染結果
建議將 scenes/ .build/ boards/stills/ out/ 加入 gitignore。
1. 旅程
當存在旅程檔案時使用它(docs/journeys/*.md:Start:、編號步驟、Expect: 檢查、
> Note: 行)。如果已安裝 browser-journeys 技能,它擁有該格式及其執行規則,
你應遵循它們。還沒有旅程?先與使用者一起撰寫一個:示範的品質取決於步驟。
在執行之前,請在一條訊息中提出你的建議:
- 主機:本機或測試環境;絕不可是正式環境,除非他們明確要求。
- 分支:當旅程提供選擇時(從函式庫複製或撰寫新的、已儲存的卡片或新卡片), 示範應展示哪個路徑。預設值:最短的快樂路徑。
- 數值:旅程的測試值(「旅程測試 — 請忽略」)或你建議的示範友善值。 預設值:建議示範友善值,並在它們出現的所有地方使用。
- 訊息與觀眾:根據旅程草擬兩者;他們確認。
- 副作用:說明此執行在該主機上會建立什麼(帳戶、訂單、出價)以及旅程的清理機制(如果有的話)。
為另一個主機編寫的旅程(Start: local、種子指令、從開發日誌讀取的代碼)?
其設定行屬於該主機:詢問在此主機上的對等項目,絕不要猜測。
2. 執行並擷取
resize_window至 1440×900,並在整個執行過程中保持該尺寸:每個幀必須共用一個 檢視區,且建置工具會拒絕混合尺寸。- 按照旅程的指示執行每個步驟。檢查每個
Expect:;失敗時,停止並回報。示範 絕不能建立在有問題的流程上。擷取執行不必以可觀看的速度進行:每次凍結前只需等到 頁面穩定下來即可。 - 登入和角色切換由使用者處理。 說「請以 <角色> 登入,完成後告訴我」,等待,然後繼續。 旅程列印到你啟動的開發日誌中的代碼可由你輸入;絕對不要輸入密碼或來自某人收件匣的代碼。 不要凍結登入畫面(它們會顯示電子郵件):故事板會從登入前跳到登入後。
- 選擇幀:每次點擊一個幀。 幀是指觀眾需要跟隨流程的那個點擊之前的畫面。
打字、勾選和選擇在凍結之前完成,這樣幀顯示它們已完成;當幀應顯示空欄位時,請在打字之前凍結。
透過 URL 到達或沒有東西可按的畫面是一個沒有
click的幀(它會淡入)。跳過設定和 登入。目標是 4–8 個幀,並且總是凍結最後一個畫面。 - 凍結:將整個
scripts/freeze.js貼到頁面中(使用javascript_tool,每次頁面載入一次;typeof window.__freeze會告訴你),然後await window.__freeze('03-open-the-orbit')(兩位數的順序,然後是一個代號)。比較它返回的viewport與第一個幀的;如果不同(因為下載或資訊列開啟),關閉該列並再次凍結。 - 每次凍結都會將
<name>.html下載到~/Downloads。當執行結束時,將它們移動到snapshots/。 再次凍結同一個名稱會使 Chrome 儲存<name> (1).html:先刪除舊的下載。 如果 Chrome 詢問是否允許多次下載,由使用者點擊「允許」。
3. 撰寫 STORYBOARD.md
HyperFrames 的故事板格式。每個凍結畫面一個幀:
---
message: 在一分鐘內開啟 Orbit
audience: 正在決定是否嘗試 ShoutOrbit 的 YouTube 創作者
journey: docs/journeys/create-an-orbit.md (步驟 4–5, 測試環境, 2026-11-13)
url: staging.shoutorbit.com
status: draft
---
## 幀 3:開啟 Orbit (8-12s)
- duration: 4s
- snapshot: 03-open-the-orbit.html
- click: 開啟 Orbit
- scene: 日期和出價會自動填入
表單底部,日期已填好。游標按下「開啟 Orbit」。
開放問題:標題欄位仍顯示其預留位置文字。是在畫面上鍵入它,還是保留原樣?
click:元素的完整標籤,完全一致:其可見文字、值、預留位置或 aria-label(「下標 · $25」,而不是「下標」)。建置工具在每次執行時找到它,如果找不到則會 大聲失敗。在沒有點擊的幀上省略它。duration:在畫面上的秒數,3–5;省略時預設為 4s。scene:畫面上的說明文字:簡短,關於觀眾看到了什麼(「日期會自動填入」), 而不是他們按了什麼。- 計畫行:幀顯示的內容和游標的動作,以簡單文字說明。
- 開放問題: 每行一個使用者必須決定的事項。查看每個凍結畫面中的: 測試或垃圾資料;個人資料(電子郵件、真實姓名、帳號);應放置真實值但為預留位置處; 與畫面矛盾的說明文字(在「尚未接受出價」上方顯示「競標中」);過時的日期。提出它們; 絕不要默默修復。
4. 建置並交付看板
node <技能>/scripts/demo.mjs serve docs/demos/<slug> --port 4321 # 在背景執行
它會建置,然後提供服務於 http://127.0.0.1:4321/。為使用者開啟它(Chrome 或 open)然後停止。
在看板上,他們可以變更說明文字、點擊目標、秒數、標題和順序、移除幀、
為 Claude 撰寫筆記、在擷取的頁面上重新輸入文字(編輯頁面文字;重新命名已點擊的元素會將點擊動作一併帶走),
然後按下批准渲染。每次儲存都會重建靜態畫面。
5. 處理筆記
當他們說已留下筆記時,讀取 STORYBOARD.md。對於每個 > Note: 行:
| 他們要求 | 變更內容 |
|---|---|
| 說明文字、時間、順序、點擊 | STORYBOARD.md 中該幀的按鍵值 |
| 頁面上不同的文字 | 該 snapshots/*.html 中的文字(僅文字:保留標籤和類別) |
| 未擷取的畫面,或不同的狀態 | 再次執行該旅程步驟並凍結它 |
| 流程無法顯示的內容 | 說明原因;提供最接近的真實版本 |
然後將筆記轉換為 > Done: <變更的內容>(看板會將這些顯示為已完成),在 frontmatter 中將
status 設為 draft(只有使用者能批准),執行
node <技能>/scripts/demo.mjs build docs/demos/<slug>,然後告訴他們重新整理看板。
伺服器可以繼續執行。
6. 渲染
僅當 frontmatter 顯示 status: approved,或者使用者在聊天中說「進行」時:
cd docs/demos/<slug> && npx hyperframes check && npx hyperframes render -o out/<slug>.mp4
關於子組合、軌道密度和無聲影片的 check 警告是預期的。為他們開啟 MP4。
如果稍後 UI 變更,再次執行旅程,重新凍結畫面已變更的幀,
保留故事板,然後渲染:這就是整個更新過程。
常見錯誤
| 症狀 | 原因與修正 |
|---|---|
| 游標落在目標下方或旁邊 | 幀以不同的視窗大小擷取,或頁面正在滾動中。以同一尺寸重新擷取。 |
建置工具顯示 nothing labelled "…" | click 文字與畫面不完全匹配(大小寫、空格、→)。從頁面複製它。 |
probe viewport was … | 無頭 Chrome 的視窗邊框已變更;調整 demo.mjs 中的 CHROME_UI。 |
| 幀顯示空欄位 | 在輸入之前凍結。先填入,再凍結。 |
| 幀中缺少圖片或字型 | 跨來源提供服務但未設定 CORS,因此 freeze.js 保留了 URL;它們僅在該主機啟動時載入。將其標記為開放問題。 |
| Stripe 或其他 iframe 為空白 | freeze.js 會移除 iframe。在它們之前或之後凍結畫面,或說明缺少了什麼。 |
Chrome not found | 設定 CHROME=/path/to/chrome。 |
隱私
快照包含螢幕上的一切內容,圖片已內嵌。在任何人分享看板、資料夾或影片之前,請檢查幀中是否有個人資料,並將其作為開放問題提出。