はじめに
「この操作、どうやるんでしたっけ?」
社内システムの使い方を聞かれるたびに、スクショを撮って、赤枠つけて、「ここをクリックします」と書いて...。気づけば30分経っている。
この無駄な時間をなくしたくて、ブラウザ操作を自動でキャプチャして手順書を作るChrome拡張機能を作りました。
手順キャプチャ(Procshot)をChrome ウェブストアで見る
作ったもの
手順キャプチャ(英語名: Procshot)
「撮影開始」ボタンを押して普通にブラウザを操作するだけで、スクショ付きの手順書が自動で完成します。
主な機能
- 📸 クリック・入力・ページ遷移を自動検出してスクショ撮影
- ✏️ 「検索ボタンをクリックします」など説明文を自動生成
- 🎯 クリック位置を枠や矢印で強調
- 📤 HTML / Markdown / PDF でエクスポート
特徴
- 完全ローカル動作: スクショや操作データは外部に送信されません
- 日本語ネイティブ対応: 説明文が自然な日本語で生成されます
- $9/月: 競合(Scribe $23、Tango $20)より安い
技術スタック
Chrome Extension (Manifest V3)
├── React 18
├── TypeScript
├── Vite + CRXJS
├── Tailwind CSS
└── IndexedDB (idb-keyval)
サーバーレスで、すべての処理がブラウザ内で完結します。
技術的に面白かったところ
1. スクショのタイミング問題
最初は「クリック後にスクショを撮る」実装にしていましたが、これだと問題が発生しました。
ユーザーがボタンをクリック
↓
ページが遷移
↓
スクショ撮影 ← この時点でクリックしたボタンはもう画面にない!
解決策として、クリック前にスクショを撮るように変更しました。
document.addEventListener('click', async (event) => {
// 1. クリック前に即座にスクショ
const screenshot = await captureVisibleTab();
// 2. 要素情報を取得(まだDOMにある状態で)
const element = event.target;
const rect = element.getBoundingClientRect();
// 3. ステップとして記録
saveStep({ screenshot, rect, ... });
// 4. クリックは通常通り実行される
}, true);
2. クリック対象の特定
ユーザーが <div> の中の <button> の中の <span> をクリックした時、イベントターゲットはどれになるか?
答えは「場合による」です。イベントバブリングにより、実際にクリックした要素より親要素がターゲットになることがあります。
そこで、意味のある要素を探索するロジックを追加しました。
function findMeaningfulElement(target: Element): Element {
const genericTags = ['DIV', 'SPAN', 'BODY', 'SECTION'];
// ターゲットが汎用要素なら、子要素から意味のある要素を探す
if (genericTags.includes(target.tagName)) {
const button = target.querySelector('button, a, input, [role="button"]');
if (button) return button;
}
return target;
}
3. 説明文の自動生成
クリックした要素から「何をクリックしたか」を説明するテキストを生成します。
優先順位:
-
aria-label属性 -
placeholder属性 -
innerText(アイコン要素を除外) - タグ名からの推測(「ボタンをクリックします」)
function getElementText(element: Element): string {
// aria-labelを優先
const ariaLabel = element.getAttribute('aria-label');
if (ariaLabel) return ariaLabel;
// placeholderをチェック
if (element instanceof HTMLInputElement && element.placeholder) {
return element.placeholder;
}
// innerTextからアイコンを除外して取得
const clone = element.cloneNode(true) as Element;
clone.querySelectorAll('svg, [class*="icon"]').forEach(el => el.remove());
return clone.textContent?.trim() || '';
}
ただし、これだと「open_in_new」(Material Iconのaria-label)などが混入することがあったので、除外パターンも追加しています。
4. SPAのページ遷移検出
ReactやVueなどのSPAでは、従来の beforeunload イベントが発火しません。代わりに History API を監視します。
// pushState/replaceState をラップして検出
const originalPushState = history.pushState;
history.pushState = function(...args) {
originalPushState.apply(this, args);
handleNavigation();
};
// popstate(ブラウザの戻る/進む)も検出
window.addEventListener('popstate', handleNavigation);
5. 撮影中のオーバーレイUI
撮影中であることをユーザーに伝えつつ、オーバーレイ自体がスクショに映り込まないようにする必要がありました。
const overlay = document.createElement('div');
overlay.setAttribute('data-procshot-ignore', 'true');
document.body.appendChild(overlay);
// スクショ撮影時にオーバーレイを一時的に非表示
async function captureScreenshot() {
overlay.style.display = 'none';
const screenshot = await chrome.tabs.captureVisibleTab();
overlay.style.display = 'block';
return screenshot;
}
苦労したところ
Manifest V3 の制約
Chrome拡張のManifest V3では、Service Workerが非アクティブ時に停止します。これにより、録画状態の管理が複雑になりました。
// Service Workerが再起動するたびに状態を復元
chrome.storage.local.get('recordingState', (result) => {
if (result.recordingState?.isRecording) {
// 録画を再開
resumeRecording(result.recordingState);
}
});
権限の最小化
Chrome Web Storeの審査では、権限の正当性が厳しくチェックされます。<all_urls> 権限を使う理由を明確に説明する必要がありました。
この拡張機能は、ユーザーが閲覧しているWebページでスクリーンショットを撮影し、クリック位置を検出するために、すべてのURLへのアクセス権限が必要です。
今後の予定
- AI による説明文の改善(Gemini API 連携)
- インタラクティブ再生(実際のページ上でガイド表示)
- チーム共有機能
おわりに
個人開発で14個目のChrome拡張機能になりました。
「こういう機能がほしい」「ここがおかしい」などフィードバックいただけると嬉しいです!
手順キャプチャ(Procshot)をChrome ウェブストアで見る
S-Hub では、生産性向上のためのツールを開発しています。他の拡張機能もぜひチェックしてみてください。
作った拡張機能
🎯 生産性ツール
- PromptStash - AIプロンプトを保存・管理(19サービス対応)
- DataPick - Webページからデータを抽出
- SnippetVault - コードスニペット管理
- ReadMark - 読書位置を記憶
🧘 デジタルウェルビーイング
- YouTube Shorts Killer - YouTubeショートを非表示
- X Detox - X(Twitter)のノイズを消す
- ZenRead - 集中読書モード
🛒 EC・せどり
- 楽天セラーズ・アナリティクス - 楽天市場の出品者分析
- Arbitra - 価格比較ツール
🔧 Web便利ツール
- Japanese Font Finder - Webサイトの日本語フォントを特定
- TVerPlus - TVerの視聴体験を改善
- Yahoo快適 - Yahoo!の閲覧体験改善
🏠 不動産
すべての拡張機能の詳細 → S-Hub
📝 この記事は Zenn にも掲載しています → https://zenn.dev/ktg/articles/55b63d68ac2ddb