あなたはストア用スクリーンショットセットをデータとして構築します。各タイルは HTML キャンバスで構成され、背景、ヘッドライン、実機キャプチャを保持する端末フレーム、そして画面から3Dで浮かび上がったブレイクアウト(キャプチャの切り抜きまたはベクター吹き出し)のレイヤーを持ちます。すべての文字列は locales/<locale>.json に格納されるため、新しい言語は1つの JSON ファイルとキャプチャ画像を追加するだけで対応でき、レンダリングは決定論的です。同じ入力から同じピクセルが得られます。
以下、$S はこの SKILL.md が置かれているフォルダ、$PY は $S/.venv/bin/python です。仮想環境がない場合は、一度作成します:
python3 -m venv $S/.venv && $S/.venv/bin/pip install -r $S/requirements.txt && $S/.venv/bin/playwright install chromium
パイプライン:
1 メリットの分析 -> 2 スライドの設計 -> 3 capture.json -> 4 キャプチャ(シミュレータ)-> 5 構成
-> 6 背景 -> 7 set.json + locales -> 8 レンダリング -> 9 レビュー ->(さらに言語、端末)
リポジトリ内の $S/../../examples/demo/ は完全なプロジェクト例です(架空のアプリ、2言語、5台の端末)。独自の set.json を作成する前に、このサンプルを参照してください。
プロジェクトのレイアウト
<project>/
capture.json アプリ、キャプチャ端末、キャプチャする画面を定義
set.json 全ロケールで共有する構成
locales/<locale>.json すべての文字列:動詞、サブライン、吹き出しテキスト
sim/<locale>/<slide>.png 電話キャプチャ(キャプチャセットごとに1フォルダ)
sim-tablet/ sim-duo/ sim-android/
fonts/ assets/ オプション:フォント、背景画像、プロップス
out/<locale>/<device>/ ストアファイルのみ
out/_sheets/ ロケールと端末ごとのコンタクトシート
out/_captures/ ロケールごとのキャプチャ後のコンタクトシート
アプリのリポジトリルートに store-screenshots/ を配置することを推奨します。out/ と .cache/ は .gitignore に追加してください。
1. メリットの分析(Benefits)
コードベースを読み込みます:ナビゲーション(タブ、ルート、画面)、オンボーディングのコピー、ペイウォールのコピー、README、既存のストア掲載情報。ユーザーが得られるもの(インストールに大きく寄与するもの)を5〜8個リストアップします。スライドごとに1つのメリットです。
各スライドのヘッドラインは、1つの短い動詞を大文字で、サブラインは最大2行です:PLAN / YOUR WEEK IN MINUTES、SAVE / ON EVERY SHOP。動詞はメリットを表し、機能ではありません。各メリットを証明する画面とともにリストを示し、承認を得てください。
2. スライド(Slides)
IDは NN-name 形式。番号はストアでの表示順です。スライドごとに使用する画面を選び、必要な状態(ログイン済み、データあり、シートが開いているなど)をメモします。画像が多い画面は傾け、データ密度の高い画面はそのままにします。
3. capture.json
$S/templates/capture.json をテンプレートとして使用します。
| キー | 意味 |
|---|---|
app.ios | bundleId、および app(シミュレータ用 .app ビルドへのパス)または copyFrom(アプリがインストール済みのシミュレータの UDID) |
app.android | package、オプションの activity、オプションの apk(インストール用) |
devices.<key> | platform ios または android、dir(キャプチャフォルダ)、iOS:name(専用シミュレータ、setup で作成)と type(xcrun simctl list devicetypes から)、オプションの runtime;Android:avd(emulator -list-avds) |
| 端末の追加設定 | appearance(light)、locale(以下のモードを上書き)、displaySize(2853x2007 は iPhone Duo の内部ディスプレイを指定)、rotate(度、キャプチャが横向きになる場合) |
locale | プラットフォームごと。iOS は reboot(デフォルト、最も信頼性が高い)、relaunch(再起動なし、折りたたみ端末の姿勢を維持)、または launchArgs。Android は app(デフォルト、Android 13以上のアプリ単位の言語、アプリの localeConfig が必要)または system(ルート権限のあるエミュレータイメージが必要) |
launch | 起動後の wait 秒数、オプションの url(起動時に開く代わりの URL。Expo 開発クライアントの URL など)、オプションの steps |
screens | {id, steps, ready, after, devices, copyFrom} のリスト。さらに byDevice / byLocale ブロックで画面ごとにオーバーライド可能 |
ステップは順に実行され、各ステップは wait(デフォルト1〜2秒)で待機します:
| ステップ | 効果 |
|---|---|
{"open": "myapp://route"} | ディープリンク。タップよりも推奨:すべての端末とプラットフォームで動作 |
{"tap": {"label": "Save"}} | そのアクセシビリティラベルを持つ要素をタップ(または {"id": ...})。完全一致、次に部分一致 |
{"tap": {"at": [0.5, 0.9]}} | 画面の指定割合の位置をタップ |
{"tap": {...}, "until": {"label": "Details"}} | その要素が表示されるまでタップを繰り返す(最大3回)。画面が安定しない場合に使用 |
{"waitFor": {"label": "Done", "timeout": 20}} | 要素が画面に表示されるまで待機。読み込みやアニメーションのある画面のタップ前などに使用 |
{"type": "pasta"}, {"key": "enter"}, {"key": "back"} | テキスト入力とキー操作 |
{"swipe": [0.5, 0.8, 0.5, 0.3]} | スワイプ(割合で指定) |
{"launch": true} | アプリの再起動 |
ready: {"region": [x, y, w, h], "minStd": 20, "tries": 5, "delay": 3} は、指定領域が単一色(スケルトン行、スピナー、読み込み中の画像)である間、再キャプチャを行います。iPhone キャプチャは、シミュレータが Dynamic Island をキャプチャに焼き付けてしまった場合に自動的に再取得されます。
copyFrom: "01-home" は、その端末で別のキャプチャを再利用します(タブレットが分割ビューで2画面を表示する場合など)。devices: ["phone"] は、特定の端末にのみ画面を制限します。
capture.py PROJECT describe --device phone は、タップ可能な要素をラベルとフレーム付きで表示します。
4. キャプチャ(Capture)
$PY $S/capture.py <project> doctor ツール、端末、アプリ ID の確認
$PY $S/capture.py <project> setup 専用シミュレータの作成/起動、AVD の起動、アプリのインストール
$PY $S/capture.py <project> run --locale en-US すべての端末と画面をキャプチャ
$PY $S/capture.py <project> run --locale en-US --device phone --screen 03-search
- キャプチャ端末は専用です:iOS シミュレータは名前で作成され(
Capture iPhoneなど)、Android は capture.json で指定された AVD を使用します。capture.json をユーザーが作業中のシミュレータに向けてはいけません。また、端末の起動や言語切り替えの前に確認を取ってください。 setup後、アプリは通常デモ状態が必要です:デモアカウントへのログイン、データのシード、初回起動ダイアログ(パスワード保存、通知、レビュープロンプト)の解除。端末ごとに1回実行してください。この状態は言語切り替え後も維持されます。デモ用の認証情報はユーザーに確認してください。決して capture.json に書き込まないでください。- デバッグオーバーレイ(開発メニューボタン、トースト)を表示する開発ビルドは、キャプチャセッション中はそれらを非表示にする必要があります。ローカルでパッチを当て、コミットしないでください。
out/_captures/<locale>.jpgをタイルごとにレビュー:別の言語の文字列、ダイアログ、トースト、スピナー、空の状態がないか確認します。データやステップを修正し、該当画面を再実行してください。レンダラーはキャプチャをそのまま使用します。ミスを塗りつぶすことはありません。- iPhone Duo:折りたたみを解除し、横向きに設定してからシミュレータまたは DeviceHub で使用してください。simctl は折りたたみや回転を制御できません。ディープリンクを使用し(HID タップが内部ディスプレイに届かない場合がある)、
"locale": "relaunch"と"displaySize": "2853x2007"を設定してください。
クロスプラットフォームアプリ(React Native、Flutter)は Android キャプチャをスキップできます:Android タイルは iPhone と iPad のキャプチャを再利用します(これがデフォルトの動作です)。ネイティブ Android アプリは独自の画面を sim-android/ にキャプチャします(セクション10参照)。
5. 構成(Composition)(レンダリング前にユーザーが承認)
各スライドを ASCII アートでスケッチ:ヘッドライン、端末の位置と傾き、どの要素をブレイクアウトし、どこに配置するか。承認を得てから set.json を記述します。
+------------------------------+
| WATER | 動詞、1行
| EVERY PLANT RIGHT | サブライン、最大2行
| ON TIME |
| .--------------. |
| [* 3 plants today] | 吹き出し、浮かび上がり、左にはみ出す
| | Today ... | | 端末は y 方向15度、x 方向4度傾ける
+------------------------------+
6. 背景(Background)
セットごとに1つの背景で、全ロケール・全端末で共有します。CSS で指定するか("background": {"css": "radial-gradient(...), #1f4a37"}、デモはこちらを使用)、画像を使用します({"image": "assets/bg.png"}、background-size cover)。画像ジェネレーターは柔らかいプレートに適しています。ブランドカラーでソフトな照明が当たったシームレスな9:16のスタジオ背景をプロンプトし、以下の点を明示的に指定してください:オブジェクトなし、テキストなし、端末なし、形状なし。2枚生成し、ユーザーが選択します。プロップス(ステッカー、商品写真)はアルファチャンネル付き PNG で、スライドごとに配置します。
7. set.json と locales
すべての矩形は measure.py でキャプチャピクセル単位で測定します。目測は禁止です:
$PY $S/measure.py sim/en-US/05-fill.png --at 700,790 ボタン、チップ、ピルをフラッドフィル
$PY $S/measure.py sim/en-US/01-plan.png --ink 40,415,700,75 プレーン領域のテキスト境界
$PY $S/measure.py sim/en-US/02-cook.png --grid 440,1510,340,110 ズームグリッド画像(テンポラリディレクトリ)
| キー | 意味 |
|---|---|
locales, devices | フルレンダリングでカバーするロケールと端末。端末 ID は $S/devices/devices.json から |
background | {"image": ...} または {"css": ...}、オプションの position |
fonts | {"family": "fonts/File.otf"}、パスはプロジェクトからの相対パス。デフォルトの display はバンドルされた Archivo Black |
headline | font, descFont, verbColor, descColor, shadow, verbTracking, descTracking, descWordSpacing |
capture | platform, statusBarBand(キャプチャから除去する行。iOS デフォルト [66, 128])、sets({"tablet": {"dir": "sim-tablet", "statusBarBand": [12, 56]}})、devices({"android-phone": "android"} のように、特定の端末を別のキャプチャセットに向ける) |
style | gloss, deviceShadow, thicknessRatio(側面の奥行き)、sideLayers |
statusBar | time, color(レンダラーが描画するステータスバーの色) |
layout | 端末 ID ごと。devices.json のレイアウトを上書き(deviceTop, deviceWidth, verbMax ...) |
baseline | {device: {locale: folder}}(既存のセットのベースライン。--compare で使用) |
slides | リスト(以下参照) |
スライド:id, sim(キャプチャファイル名、デフォルトは <id>.png)、tilt {x, y, z} 度、offset {x, y}(キャンバスの割合)、layout, breakouts, props(src, x, y, w(キャンバスの割合)、rotate, shadow, z:front または back)。
ブレイクアウト:
| キー | 意味 |
|---|---|
type | crop:キャプチャのピクセルをそのまま使用。callout:ロケールテキストを持つベクターピル |
rect または anchor | [x, y, w, h](キャプチャピクセル単位)。元の要素の位置 |
at または dx/dy | 配置位置(at = キャプチャピクセル単位の新しい左上。またはオフセット) |
scale, lift | サイズと Z 方向の浮き上がり量(ピクセル単位、デフォルト80) |
vacate, vacatePad | 元の位置を周囲の色で埋める(移動(コピーではない)) |
radius, shadow, origin | 角丸半径(キャプチャピクセル単位)、影の強さ、変形の原点 |
text, icon, style | 吹き出し:ロケールの callouts のキー、tag または sparkles、font, size, bg, fg, padX, padY, gap, radius, weight, tracking, iconScale, iconColor |
slides 内部の任意の値は、端末とロケールごとにバリエーションを持たせることができます:
{"byDevice": {"phone": ..., "tablet": ..., "default": ...}}(キー:端末 ID、キャプチャセット、default)および {"byLocale": {"de-DE": ..., "default": ...}}、どちらもネスト可能。矩形はほとんどの場合ロケールによって異なります(同じチップでもドイツ語では横幅が広くなります)。
切り抜きは、大きな要素で最大約1.7倍までシャープさを保ちます。小さなチップやテキストは吹き出し(ベクター)にし、どの倍率でもシャープに保ちます。
ロケールファイル:
{
"captures": "en-US",
"dir": "ltr",
"fonts": {"display": "fonts/NotoSansJP-Black.otf"},
"slides": {
"01-plan": {"verb": "Plan", "desc": "Your week in minutes", "callouts": {"savings": "approx. €7.81 saved"}}
}
}
必須なのは slides のみです。captures は、あるロケールが別のロケールのキャプチャを再利用することを可能にします(en-GB が en-US のキャプチャを読み取るなど)。headline と statusBar は set.json の値を上書きします。Archivo Black はラテン文字のみ対応。キリル文字、ギリシャ文字、CJK、アラビア語、ヘブライ語は fonts のオーバーライドが必要です。RTL は "dir": "rtl" が必要です。
8. レンダリング(Render)
$PY $S/render.py <project> すべてをレンダリング
$PY $S/render.py <project> --locale de-DE --device iphone-67 --slide 01-plan
$PY $S/render.py <project> --compare ベースラインと新規シートの比較
ヘッドラインのサイズは、同じロケール・端末のすべてのスライドで共有されます。そのため、セット全体が統一された印象になります。キャプチャのアスペクト比が端末の画面開口部と一致しない場合、レンダラーは停止します。
9. レビュー(Review)
out/_sheets/<locale>-<device>.jpg を開き、すべてのブレイクアウトを拡大して確認します。CHECK と表示された行は問題を示します(ヘッドラインが最小サイズ、重なりなど)。ヘッドラインが最小サイズになっている場合は、コピーが長すぎます。制限値を下げるのではなく、コピーを短くしてください。シートをユーザーに見せて確認を得てください。
10. 言語と端末の追加(More languages and devices)
言語を追加する:
$PY $S/add_locale.py <project> es-ES init --from en-US ロケールファイル、byLocale プレースホルダ、フォルダを作成
$PY $S/capture.py <project> run --locale es-ES キャプチャ
# locales/es-ES.json を翻訳:ストアコピー、短い動詞、キャプチャに合った吹き出し
$PY $S/add_locale.py <project> es-ES measure --from en-US 矩形を再検出、並べて表示した画像を確認
$PY $S/add_locale.py <project> es-ES measure --from en-US --write
$PY $S/add_locale.py <project> es-ES check レンダリング前にエラーが0であることを確認
$PY $S/render.py <project> --locale es-ES
地域バリアント(en-GB、de-AT、fr-CA):init --share-captures で、テキストのみが変更されます。
$S/devices/devices.json の端末:
| ID | キャンバス | 読み取り元 | ストアスロット |
|---|---|---|---|
iphone-67 | 1290x2796 | phone (1206x2622) | ASC APP_IPHONE_67 |
android-phone | 1080x1920 | phone | Play 電話スクリーンショット |
ipad-13 | 2064x2752 | tablet (2064x2752) | ASC APP_IPAD_PRO_3GEN_129 |
android-tablet | 1792x2400 | tablet | Play 7" および 10" タブレット |
iphone-duo | 2853x2007 | duo (2853x2007) | ASC iPhone Duo |
フレームは make_frame.py で作成された汎用の図形で、再配布は自由です。一致するフレームがないキャプチャサイズは、新しくフレームを生成します:
# ネイティブ Android キャプチャ(1080x2400)を sim-android/ に
$PY $S/make_frame.py --style android --screen 1080x2400 --device android-phone --captures android
# 次に set.json で: "capture": {"sets": {"android": {"dir": "sim-android", "statusBarBand": [30, 105]}}}
スタイル:ios, android, tablet, landscape。--canvas WxH で新しい端末 ID のストアサイズを設定します。statusBarBand は実際のキャプチャから測定します:ステータスバーの行数+キャプチャ上でマージする必要のあるマージンです(マージしないとキャプチャの上端とフレームの間にストアが不自然な空白を表示します)。Android では、ステータスバーが透明でコンテンツが表示される場合があるため、バンドはキャプチャのコンテンツ領域の先頭行まで含める必要があります。
11. バージョン管理(Versioning)
新しいアプリビルドは、変更の有無にかかわらずキャプチャを無効にします。capture.json の "app" パスが新しいビルドを指す場合、古いキャプチャは使用されず、再キャプチャが必要です。バージョン管理テーブルは不要です。
--compare フラグは、set.json の baseline セクションを使用して、以前のベースラインセットからの変更を検出します。out/_sheets/ の各シートは、_baseline プレフィックス付きの対応するシートと比較され、ピクセル単位の差分が強調表示されます。これは、吹き出しの位置やテキストの折り返しが予期せず変更された場合に役立ちます。