自動更新されるスクリーンショット
(interblah.net)- 実行中のWebアプリケーションで スクリーンショットを自動キャプチャ し、ヘルプ文書のビルドとあわせて更新する流れにより、UI変更後も文書内の画像を 最新の状態 に保ちやすい
- Markdown 内の
SCREENSHOTコメントが対象パス、キャプチャ方式、CSS selector のような指示を持ち、ビルド時にそれを読み取って実際の画像で埋め込む - Rake task が Capybara と Cuprite を通じて headless Chrome を実行し、チームごとに処理をまとめて一度ログインした後、複数の URL を巡回してキャプチャする
- キャプチャは element、full_page、viewport の3つのモードをサポートし、
click、wait、crop、torn、hideのようなオプションで開いた状態の UI や不要な要素も制御する rails manual:buildを一度実行するだけでスクリーンショット生成とヘルプページのビルドがまとめて動き、コードと文書を 同じPRやcommit の中で揃えやすくなるため、手動キャプチャや手動クロップの摩擦が大幅に減る
自動更新されるスクリーンショット方式
- Jelly のヘルプセンターは、実行中のWebアプリケーションで スクリーンショットを自動キャプチャ し、再ビルド時にあわせて更新されるよう構成されている
- 文書は Markdown で書かれ、Self-updating screenshots の本文をもとに Redcarpet で HTML に変換した後、Rails アプリの ERB ビュー としてレンダリングされる
- Markdown 内には
SCREENSHOTコメントが入り、ここに対象パス、キャプチャ方式、CSS selector のような指示をまとめて記述する<!-- SCREENSHOT: acme-tools/inbox | element | selector=#inbox-brand-new-section -->- 直下の画像タグが結果画像の入る位置として使われる
- UI の色、ボタン位置、文言が少し変わるだけでも既存の文書スクリーンショットはすぐ古くなるが、この流れはそうした手動更新の負担を減らす
キャプチャパイプラインと保守効果
- 内部では Rake task が Capybara と Cuprite を使って headless Chrome を実行し、すべての Markdown ファイルの
SCREENSHOTコメントをスキャンする - スクリーンショット作業はチーム単位でまとめて処理され、同じチームでは 一度だけログイン した後に複数の URL を巡回する構成になっている
- サポートするキャプチャモードは3つある
- element: CSS selector で特定の DOM 要素をキャプチャする
- full_page: ページ全体をキャプチャし、必要なら高さ基準で切り取れる
- viewport: ブラウザウィンドウで現在見えている領域だけをキャプチャする
- 詳細オプションとして click、wait、crop を指定でき、ボタンクリック後に現れる状態やアニメーション後の画面も自動で取得できる
<!-- SCREENSHOT: nectar-studio/manage/rules | full_page | click=".rule-create-button" wait=200 crop=0,800 -->- ボタンを押してフォームを開いた後、200ms 待機し、特定領域に切り取ってキャプチャする動作になる
- 追加オプションとして torn と hide もある
tornは CSS のclip-pathを使って、破れた紙の縁のような効果を適用するhideは dev toolbar や cookie banner のように画面に出すべきでない要素を一時的に隠す
- パイプライン全体は
rails manual:buildコマンド一つで実行され、すべてのスクリーンショットキャプチャ と ヘルプページのビルド をまとめて処理する - 文書ソースは
public/manual/配下に basics、setup、advanced のようなセクション別で整理されている - ビルド段階でこれらの Markdown ファイルは
app/views/help/配下の ERB ビュー に変換され、breadcrumb とセクションナビゲーションもあわせて生成される - 機能開発とヘルプ更新を同じコードベース内で一緒に扱えるため、コードと文書の同期 を同じPRや同じcommitの中で保ちやすくなる
- スクロールが必要な要素、クリックしないと開かない popover、不要部分を避けるための crop といった 例外処理 は実装により多くの時間を要したが、構築後はヘルプセンターをはるかに高頻度で更新できるようになった
- UI を変更してビルドを再実行し、その結果を commit する流れだけでスクリーンショットを常に最新状態に保てるため、手動キャプチャや手動クロップの摩擦はほぼなくなる
1件のコメント
Hacker Newsのコメント
プログラムでスクリーンショットを生成するついでに、アプリの light/dark theme 2バージョンも一緒に作って、
prefers-color-scheme: darkに合わせて差し替えればよいです。こうした要素は GitHub README でもうまく動きます: https://github.com/CyberShadow/CyDo#readme
モバイルアプリでは Nix で使い捨ての Android エミュレータを立ち上げて最新のスクリーンショットを生成するようにしていて、事前設定も不要ですし、実行後にデータも残りません。
自分の場合、設定自体もそれほど大変ではなく、むしろアイデアを思いつく方が難しく、Nix コードはお気に入りの LLM で一発で作りました。
手動でスクリーンショットを更新するのは世界でいちばんつらい作業というわけではありませんが、
upload-apk + take-screenshot + transfer-back-to-PC + editという流れがいつも微妙に面倒で、結局ほとんどやらなくなってしまいます。文脈からだいたい推測はできましたが、それでも不便でした。
アプリストアではスクリーンショットが必須ですが、画面サイズの数とローカライズの数だけ画像を作らなければならず、すぐに面倒になります。
以前はこのために自分でスクリプトを書いていましたが、今では https://fastlane.tools/ のような Fastlane ツールが大いに役立っています。
自分のロジックパズルゲーム Nonoverse にも Fastlane を使っていて、App Store のページでサンプルスクリーンショットを見ることができます: https://apps.apple.com/us/app/nonoverse-nonogram-puzzles/id6...
App Preview 動画の録画も複数シーンを含めて自動化していて、興味のある人がいれば別記事にまとめる価値のあるテーマだと思います。
自分が vibe coding で作っている小さなカジュアルゲームは、いつもアプリが CLI でヘッドレス実行できて、オフスクリーンテクスチャレンダリング、スクリーンショット命令、パフォーマンス計測まで可能な状態から始めています。
これを入れるのにほとんど時間はかかりませんし、エージェントが UI を自動化して重要なポイントを確認できる経路もできます。
おかげで、エージェントにスクリーンショットを更新させるのもとても簡単になります。
ビルド工程に完全に溶け込んだ形ほどきれいではありませんが、そこも今後追加してみようと思っています。
offscreen screenshot path と world pos/camera view vector を指定する CLI 引数もあり、テキストベースの入力形式でスクリプト化されたベンチマークを回しています。
この形式は、名前付きセグメント複数行と、セグメントごとの
nゲームティック長、そして各セグメントのコントロール入力で構成されています。ゲームコードを触りながらビジュアルとパフォーマンスを A/B テスト するときに、これをかなり多用しています。
自分も vibe coding がゲーム開発をどれだけ簡単にするのか、とても関心があります。
Adobe Flash の時代にはインディーゲームの生態系が本当に活気に満ちていましたが、その後はあれほどの開発しやすさに触れたものはほとんどありませんでした。
vibe coding は、その水準を初めて超えるツールのように見えます。
これを入れるのにほとんど時間はかからないという話はケースバイケースです。どの エンジン を使っているのか気になります。
Markdown 文書の中に スクリーンショット宣言 をインラインで入れられる点が、とくに気に入りました。
自分のデスクトップアプリでは、複数言語と light/dark モードのスクリーンショットを生成し、ノイズを除去し、Windows/macOS のウィンドウフレームまで適用するソリューションを作ってあります。
ここにまとめています: https://maxschmitt.me/posts/cakedesk-website-redesign#screen...
今は別スクリプトなので保守がかなり面倒ですが、markdown/mdx の一部として組み込む方向を見てみようと思います。
良い刺激を受けました。
誰も気づかない X 最高の仕事 みたいなミームとして使ってもいいくらいです。
自分が作った https://github.com/zombocom/rundoc にも似た機能があります。
主な目的は チュートリアル生成 なので、実行したコマンドの出力も文書の中に再挿入してくれます。
ツールのライブプレビューを長方形の中に入れるような形です。
ツールが軽量なら、見た目としても最適かもしれませんし、ブラウザのアクセシビリティ設定やユーザーアドオンのようなレンダリング設定もそのまま反映できます。
iommi のドキュメントでは実際にそうしています: https://kodare.net/2025/01/14/iframes-not-screenshots.html
文書用の
docs/も同じリポジトリに置いて、文書を更新する中で新しいスクリーンショットが必要になったら新しいテストを追加する、という形ならうまく合いそうです。自分も数年前にまさにこれを作り始めましたが、最終的には https://picshift.io/ のように、より汎用的な方向へ抽象化しました。
それでも スクリーンショットのユースケース は今でも本当に気に入っていて、このプロジェクトの元の名前も
ScreenSyncでした。