Screen flow
実行中のアプリから取得した実際のスクリーンショットを使用して、スタンドアロンHTML画面フローを作成します。3つのパートで構成されています。
- マッピング: 主にコードから画面と画面間のリンクを特定し、
flow.jsonに記述します。 - キャプチャ: 使用可能なエージェントツールを使って、実行中のアプリの各画面をキャプチャします。リンクごとに、そのトリガーとなるボタン、タブ、行がスクリーンショット上のどこにあるかを示すホットスポットも記録します。ビューアは各矢印をその位置から開始します。
- ビルド:
scripts/build_flow.pyでページをビルドします。このスクリプトがレイアウト、矢印、パン&ズームを処理し、画像を埋め込みます。ビューアのHTMLを自分で記述しないでください。正しいマップと良好なスクリーンショットに労力を注いでください。
以下のパスは、このスキルフォルダ(このファイルが置かれているフォルダ)からの相対パスです。
0. スコープと出力
- スコープ:
feature(「チェックアウト」や「ペアレンタルコントロール」などの1つの機能/フロー)、またはapp(全画面)。リクエストに指定がない場合は、ユーザーが名前を挙げた機能をスコープとします。機能名がない場合はアプリ全体を使用します。 - 機能スコープ: 機能に至るエントリ画面(機能を開くボタンがあるタブやホーム画面など)を含めます。これらを小さな
navグループに配置し、読者が機能の開始場所を確認できるようにします。アプリの残りの部分はキャプチャしません。 - 出力フォルダ: ユーザーが指定したフォルダを使用します。指定がない場合は、プロジェクト内の
screen-flows/<スラッグ>/を使用します:flow.json、screens/<screen-id>.png、screen-flow.html。リポジトリに書き込む前に、screen-flows/を.gitignoreに追加する必要があるかを確認してください。PNGファイルは大きくなる可能性があります。
1. ナビゲーションのマッピング(スクリーンショットの前)
コードを読んでインベントリを作成します。ランダムにクリックして回らないでください。確認すべき場所は以下の通りです。
| スタック | ナビゲーションが存在する場所 |
|---|---|
| React Router / TanStack Router | ルート設定、createBrowserRouter、<Route>、routes/フォルダ |
| Next.js / Remix / Nuxt / SvelteKit | ファイルベースルート: app/、pages/、routes/、src/routes/ |
| Angular / Vue | *-routing.module.ts、router/index.ts |
| SwiftUI / UIKit | NavigationStack、TabView、.sheet、.fullScreenCover、コーディネーター、ストーリーボード/セグエ |
| Android | NavHost/composable(...)ルート、nav_graph.xml、マニフェスト内のActivity、ボトムナビゲーションメニュー |
| Flutter | GoRouter/routes:/Navigator.push、BottomNavigationBar |
| React Native | createNativeStackNavigator、createBottomTabNavigator、Expo Router app/フォルダ |
| TV/10フィートアプリ | フォーカスベースのメニュー、レール、リモコンの戻るキー、ディープリンクハンドラー |
次に、画面をリンクするトリガー(ボタン、リンク、タブバー、メニュー、navigate(...)、router.push、.sheet(isPresented:)、ログイン後のリダイレクト、ガードなど)を見つけます。各トリガーがエッジになります。
画像を含めずに最初のflow.jsonを記述します。完全なフォーマットはreferences/flow-schema.mdにあります。簡単に説明すると:
- グループ
- プライマリナビゲーションシェル(タブバーやサイドバーの遷移先、ホーム画面、グローバルメニュー)に対して、
kind: "nav"グループを1つだけ作成します。これらの画面はキャンバスの上部に1行にまとめて配置されます。 - 機能ごとに
kind: "feature"グループを1つ作成し、画面をタスク順(例: 一覧→詳細→編集→確認)に配置します。 - オンボーディング、ログイン、サインアップは独自のフィーチャーグループに配置します。
- プライマリナビゲーションシェル(タブバーやサイドバーの遷移先、ホーム画面、グローバルメニュー)に対して、
- 画面: 個別のビューごとに1つ。モーダル、シート、ダイアログ、および重要な状態(空、エラー、ペイウォール)は、フローに関係する場合に画面としてカウントします。
stateでマークします。グループが始まる画面にentry: trueを設定します。 - エッジ: ユーザーのアクションをラベルとして記述します(例:
"「チェックアウト」をタップ"、"左にスワイプ")。kindにはback(戻りパス)、modal、redirect(自動ナビゲーション)を使用します。重要でない限り、明らかな戻りリンクは省略します。すべてのタブを他のすべてのタブにリンクしないでください。デフォルトタブから他の各タブにリンクするようにします。これにより、5タブアプリでは4つのエッジになり、20にはなりません。
python3 scripts/build_flow.py flow.json --checkでマップをチェックします。アプリ全体で画面数が約25を超える場合は、グループと画面のリストをユーザーに表示し、キャプチャを開始する前に確認を求めます。
2. 実際のスクリーンショットのキャプチャ
各プラットフォームで使用するツールとコマンドについては、references/capture.mdを参照してください。すべてのプラットフォームに共通のルール:
- まずはハーネスが提供するツールを使用します。 これにはブラウザやプレビューツール、デバイス/シミュレーターツール、Playwright/Chrome DevTools MCPサーバーが含まれます。これらがない場合は、
capture.mdの代替手段(scripts/capture_web.mjs(Playwright)、xcrun simctl io、adb exec-out screencap)を使用します。 - 自分でアプリを実行します。 プロジェクトの実行手順(README、AGENTS.md/CLAUDE.md、
package.jsonのスクリプト、実行設定)を使用します。ローカルまたは開発ビルドをテストデータとともに使用します。 - テストアカウントでログインします。 認証情報が必要な場合はユーザーに尋ねます。推測しないでください。実際の顧客のアカウントを使用しないでください。
flow.jsonにシークレットを貼り付けないでください。 - フロー全体で1つのデバイスとビューポートを使用します。 モバイルWebの場合は390×844(2倍)を使用します。デスクトップWebの場合は1440×900を使用します。ネイティブアプリの場合は、1つのシミュレーターまたはエミュレーターモデルを使用します。テーマと言語は全体で統一します。
- 可能な限りユーザーと同じ方法で各画面にアクセスします。 これによりエッジも検証されます。ステップが遅いまたは不安定な場合は、ディープリンクまたはURLで直接画面を開きます。実際のパスがマップと異なる場合は、マップを修正します。
- 画面が完全に安定するまで待ちます。 スピナー、スケルトン、画像のロード中、トースト(それがポイントでない限り)がない状態にします。開発用オーバーレイとデバッグバナーを閉じます。
- サンドボックス外で、支払い、削除、メールやメッセージの送信など、破壊的または元に戻せない操作は決して行わないでください。 確認画面をキャプチャしてそこで停止します。
- 各スクリーンショットを
screens/<screen-id>.pngとして保存し、flow.jsonにimageを設定します。 - ソース画面で各リンクのホットスポットを記録します。 ユーザーがタップする要素のバウンディングボックスです。スクリーンショットと同じ座標系(画像のピクセル、または0〜1の分数)で記述します。Webでは、
scripts/capture_web.mjsがセレクタからこれを自動的に行い、hotspots.jsonに書き込みます。ネイティブプラットフォームでは、UIツリーから要素の境界を取得します(capture.md参照)。スワイプ、自動リダイレクト、システムの戻るボタンなど、表示要素ではないリンクではスキップします。 - 保存したすべてのスクリーンショットを、画像ビューアまたはReadツールを使用して確認します。空白、クリップされている、間違った画面、ログイン壁、エラーページなどがある場合は再キャプチャします。
- 画面に到達できない場合、
imageなしでマップに残し、理由をnotesに記述します。ビューアには「スクリーンショットなし」カードが表示されます。
3. ビルドとチェック
python3 scripts/build_flow.py <out>/flow.json # <out>/screen-flow.html を書き出します
python3 scripts/build_flow.py <out>/flow.json -o docs/flow.html --max-width 900
スクリプトにはPython標準ライブラリのみが必要です。flow.jsonと同じ場所にhotspots.jsonファイルがある場合はそれを読み込みます。--hotspotsでファイルを指定することもできます。ファイルサイズを小さく保つため、PillowまたはmacOSのsipsが利用可能な場合、--max-width(デフォルト1000px)より広いスクリーンショットをダウンスケールします。
HTMLを開いて見てください。ブラウザツールでスクリーンショットを撮るか、ユーザーに開いてもらいます。その後、flow.jsonでレイアウトを修正し、再ビルドします:
| 問題 | 修正 |
|---|---|
| グループ内の画面の順序が間違っている | screensを並べ替える、entry: trueを設定する、または画面を"column": nで固定する |
| グループがシーケンスではなく、ばらばらの画面の集まりになっている | グループに"layout": "grid" |
| 長いシーケンスを1行で表示したい | "layout": "row" |
| フィーチャーが開始位置から遠く離れている | そのフィーチャーに至るエッジを追加する、または"parent": "<group-id>"を設定する |
| 矢印が多すぎる | 不要な戻りリンクを削除する、またはデフォルトタブからのみタブをリンクする |
| 矢印がスクリーンショット上の間違った位置から始まっている | そのエッジのhotspotを修正する(詳細パネルで確認) |
PNGおよびPDFエクスポート
ユーザーが画像やPDFを要求した場合、またはフローをプルリクエスト、チケット、Confluence、スライドに含める必要がある場合は、ヘッドレスでエクスポートします。これはページの「エクスポート」ボタンと同じレンダラーを使用します:
node scripts/export.mjs <out>/screen-flow.html <out>/screen-flow.png # フロー全体
node scripts/export.mjs <out>/screen-flow.html <out>/checkout.png --scope checkout # 1つのグループ
node scripts/export.mjs <out>/screen-flow.html <out>/screen-flow.pdf # 概要 + グループごとに1ページ
オプション: --theme light|dark(デフォルトはlight)、--no-hotspots、--no-group-pages(PDF)。スクリプトにはPlaywrightが必要で、capture_web.mjsと同じ方法でセットアップします。PNGを引き渡す前に確認してください。
4. 報告
ユーザーにscreen-flow.htmlのパスと、画面数およびグループ数を伝えます。スクリーンショットがない画面とその理由をリストアップします。以下のビューアコントロールについて言及します:
- ドラッグしてパン、スクロールまたはピンチでズーム。
- 画面をクリックすると拡大表示され、その画面へのリンクとからのリンクが表示されます。
- 画面またはグループ(見出し部分)をドラッグして並べ替えられます。この変更はそのブラウザに保存されます。
- ホットスポット(ツールバーボタン、または
Hキー)を有効にすると、各矢印がトリガーボタンの位置から始まります。詳細パネルではホットスポットがクリック可能で、読者はプロトタイプのようにフローをクリックスルーできます。 /で検索、Fですべてを画面に収めます。- エクスポート(ツールバー)から、全体、現在のビュー、または1つのグループをPNGまたはPDFでダウンロードできます。テーマはライトまたはダークから選択できます。PDFには概要ページとグループごとのページが含まれます。エクスポートは現在のトグル設定(ラベル、グループ間リンク、戻りリンク、ホットスポット)に従います。
- URLの末尾に
#<screen-id>を付けると、その画面が開きます。