Communitygithub.com

aubarcito48/portfolio

ビルド済みのWebアプリケーションやReactコンポーネントから、CSSや画像をインライン化した自己完結型の静的HTMLを抽出します。特定のUI状態をキャプチャしたい場合や、ページの静的なバージョンを共有したい場合、Stitchアップロード用のアセットを準備する場合に使用します。

portfolio とは?

このスキルは、ローカルで動作するWebアプリケーションから、CSSと画像がすべてインライン化された自己完結型の単一HTMLファイルを抽出するためのものです。主に2つの戦略を提供します。戦略A(Puppeteerスナップショット)は、ヘッドレスChromeを使用してレンダリング後のDOMをキャプチャし、すべてのCSSスタイルと画像をbase64データURIとして埋め込みます。戦略B(ブラウザサブエージェント)は、ページとのインタラクション(クリック、フォーム入力など)が必要な場合に適しています。また、アプリがローカルで実行できない場合の最終手段として、MockPage.jsxを使用した静的フォールバック方法も提供します。Next.js、Vue、Angularなど主要なフレームワークに対応し、ダークモードや認証が必要なページ、キャンバスグラフのインライン化など、さまざまなシナリオをサポートするフラグが用意されています。出力はファイルに直接書き込まれるため、サイズ制限がなく、Stitchプラットフォームへのアップロードに最適です。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/aubarcito48/portfolio/tree/HEAD/.agents/skills/stitch-extract-static-html

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

静的HTMLの抽出

任意のWebアプリケーションから、自己完結型の静的HTMLファイルを抽出します。

使用する戦略について

処理を開始する前に、ユーザーにどの戦略を使用するかを尋ねる必要があります。選択肢を明確に提示し、推奨デフォルトとして戦略Aを推奨し、各オプションについて簡単な長所・短所の要約を提供して、ユーザーが情報に基づいた決定を下せるように支援してください。

戦略A (Puppeteer)戦略B (ブラウザサブエージェント)
適用条件アプリがローカルで動作し、認証壁がない場合事前にページとのインタラクション(クリック、フォーム入力)が必要な場合
忠実度最高 — 算出されたスタイルが解決される高 — レンダリングされたDOM
セットアップ不要 — モックは不要不要 — モックは不要
フレームワーク任意任意
出力ファイルに書き込む — サイズ制限なしエージェントコンテキスト内で切り詰められる可能性あり

[!WARNING] チェックポイント — ユーザー確認必須。 処理を進める前に、ユーザーにどの戦略を希望するかを尋ねなければなりません。 上記の比較表を提示し、デフォルトとして戦略Aを推奨し、 明示的な承認を待ってください。ユーザーが確認するまで、自分で決定したり処理を進めたりしないでください。


戦略A: Puppeteerスナップショット(推奨)

ヘッドレスChromeを起動し、完全にレンダリングされたDOMをキャプチャし、すべてのCSSをインライン化し、画像をbase64として埋め込んだ自己完結型のHTMLファイルを生成します。任意のフレームワークで動作します — MockPage.jsxは不要です。

前提条件

  • アプリがローカルで動作していること(例: npm run dev)
  • Node.jsとpuppeteerが利用可能であること(確認: node -e "require('puppeteer')")

ワークフロー

  1. アプリを起動し、ポート番号をメモします。

    [!WARNING] チェックポイント — ユーザー確認必須。 ローカルサーバーを起動した後、スナップショットスクリプトを実行したりブラウザサブエージェントを起動したりする前に、一時停止してユーザーに確認を求める必要があります。URLとポートをユーザーに報告し、アプリが正しく起動してレンダリングされていることを確認できるようにします。ユーザーが確認するまで、スナップショットのステップに進まないでください。

  2. スナップショットスクリプトを実行:

    npx tsx <SKILL_DIR>/scripts/snapshot.ts \
      --url http://localhost:5173 \
      --output .stitch/home.html \
      --wait 2000
    
  3. 複数ページ — ルートごとに1回実行:

    npx tsx <SKILL_DIR>/scripts/snapshot.ts \
      --url http://localhost:5173 --output .stitch/home.html --wait 2000
    npx tsx <SKILL_DIR>/scripts/snapshot.ts \
      --url http://localhost:5173/pricing --output .stitch/pricing.html --wait 2000
    npx tsx <SKILL_DIR>/scripts/snapshot.ts \
      --url http://localhost:5173/dashboard --output .stitch/dashboard.html --wait 2000 --html-class dark
    
  4. 開発サーバーの後片付け: スナップショット抽出のためにローカル開発サーバーを起動した場合は、抽出が完了したら必ずサーバープロセスを停止するか、バックグラウンドタスクを終了してください。

スクリプトフラグ

フラグデフォルト説明
--url(必須)キャプチャするURL
--output(必須)出力ファイルパス
--wait1000ネットワークアイドル後の追加待機時間(ミリ秒)。遅延読み込みアプリの場合は増やしてください。
--viewport1280x800ビューポートサイズ(WIDTHxHEIGHT)
--html-class—<html>要素に追加するクラス(例: dark)
--remove-fixedfalse固定/スティッキー要素(クッキーバナー、チャットウィジェットなど)を削除
--full-heightfalseビューポートをスクロール全体の高さにリサイズ
--title—ページタイトルを上書き(ルートパス、例: /dashboard または /settings/profile)
--auth-script—認証用のデフォルトエクスポート async (page) => void 関数をエクスポートするJS/TSモジュールへのパス
--inline-canvasfalse<canvas>要素(ECharts、Chart.js、D3)をbase64の<img>タグに変換

自動的に行われる処理

  • document.styleSheets からすべてのCSSOMルールをキャプチャ(動的なVite/Tailwind開発スタイルやCSS-in-JSを保持)
  • すべての<link rel="stylesheet"> を<style>ブロックにインライン化
  • <img> の src および srcset をbase64データURIに変換(外部フォントはスキップ)
  • 同一オリジンおよび相対パスのアイコンフォントファイル(@font-face)をbase64データURIとしてインライン化し、合字がASCIIテキストとして表示されるのを防止
  • <source srcset> URLをbase64としてインライン化
  • 失敗した/無効なsrcsetエントリを削除し、ブラウザがインライン化されたsrcにフォールバックできるようにする
  • <script>タグ、Vite HMR開発スタイルブロック(createHotContext、import.meta.hot)、開発オーバーレイを削除
  • 相対CSS url() パスをインライン化前に解決

フレームワーク別注意事項

フレームワーク備考
React + Viteそのまま動作。--wait 1000。
Next.jsSSRハイドレーションには--wait 3000。URL: http://localhost:3000。/_next/image からの<img srcset>は自動的にbase64としてインライン化されます。
Angular (@angular/cli / v17+)ng serve でそのまま動作(デフォルトURL: http://localhost:4200)。Angular Material / PrimeNGのアニメーションハイドレーションと遅延読み込みルートには--wait 2000。
Vue / Nuxtそのまま動作。
Svelte / SvelteKitそのまま動作。
StorybookストーリーURLを使用: --url http://localhost:6006/?path=/story/...
SSR (Webpack)より長い--waitが必要な場合があります。

トラブルシューティング

問題解決策
画像が表示されない--wait を増やす
サーバー停止後に画像が壊れて表示されるsrcset がインライン化されたか確認 — ログで「Inlined N images」を確認。srcset URLが失敗した場合は自動的に削除され、src(インライン化済み)が使用されます。
アイコンがテキスト/セリフ装飾なしフォントで表示されるsnapshot.ts が document.styleSheets(ステップ0)からCSSOMをキャプチャし、同一オリジンのアイコンフォント(@font-face)がbase64データURIとしてインライン化されていることを確認。
Next.jsの/_next/imageがインライン化されないスナップショット実行時に開発サーバーが動作していることを確認 — スクリプトは動作中のサーバーから最適化された画像を取得します。
ダークモードが適用されない--html-class dark
出力にクッキーバナーが含まれる--remove-fixed
ページにログインが必要--auth-script ./auth.ts を使用(下記「認証が必要なページ」を参照)
チャート/グラフが空白のボックスで表示される--inline-canvas を使用して <canvas> を base64 <img> にシリアライズ
Cannot find module 'puppeteer' エラーnpm install -g puppeteer

認証が必要なページ

ログインガード(Vue RouterのbeforeEach、ReactのProtectedRouteなど)があるアプリの場合は、Puppeteerセッション内で実行される小さな認証スクリプトを作成します:

// auth-myapp.ts
import type { Page } from 'puppeteer';

export default async function authenticate(page: Page) {
  // 例1: ログインフォームに記入して送信
  await page.type('#username', 'admin');
  await page.type('#password', 'password123');
  await page.click('#login-button');
  await page.waitForNavigation({ waitUntil: 'networkidle2' });

  // 例2: Cookie/localStorageを直接注入
  // await page.evaluate(() => {
  //   localStorage.setItem('token', 'mock-jwt-token');
  // });

  // 例3: モジュール注入を介してアプリ独自のログインAPIを呼び出す(Vue/Vite)
  // await page.evaluate(() => {
  //   return new Promise((resolve) => {
  //     const script = document.createElement('script');
  //     script.type = 'module';
  //     script.textContent = `
  //       import { useUserStore } from '/src/store/modules/user.ts';
  //       import { fetchLogin } from '/src/api/auth.ts';
  //       const res = await fetchLogin({ userName: 'Admin', password: '123456' });
  //       useUserStore().setToken(res.token, res.refreshToken);
  //       window.dispatchEvent(new CustomEvent('auth-done'));
  //     `;
  //     document.head.appendChild(script);
  //     window.addEventListener('auth-done', () => resolve(true), { once: true });
  //   });
  // });
}

次に、以下のように使用します:

npx tsx <SKILL_DIR>/scripts/snapshot.ts \
  --url http://localhost:5173/#/dashboard \
  --output .stitch/dashboard.html \
  --auth-script ./auth-myapp.ts \
  --inline-canvas \
  --wait 5000

スクリプトは最初に--urlに移動し(ログインページにリダイレクトされる可能性あり)、認証関数を実行した後、認証済みセッションで元の--urlに再度移動します。


戦略B: ブラウザサブエージェントによるキャプチャ

キャプチャ前にページとのインタラクション(ボタンクリック、フォーム入力、タブ移動など)が必要な場合に使用します。ブラウザサブエージェントは完全な制御を提供しますが、大規模なページでは出力が切り詰められる可能性があります。

ワークフロー

  1. アプリをローカルで起動します。

  2. ブラウザサブエージェントを使用して移動します。

  3. 必要に応じてインタラクション(クリック、スクロール、フォーム入力)を行います。

  4. DOMを抽出: document.documentElement.outerHTML

    [!WARNING] 大規模なページは切り詰められる可能性があります。これに対処するには:

    • 抽出前に<style>タグを削除: document.querySelectorAll('style').forEach(el => el.remove())
    • スタイルを静的に再追加(Tailwind CDNリンク、ソースCSS)
  5. ファイルに保存します。


付録: 静的フォールバック (MockPage.jsx)

[!NOTE] この方法は、アプリをローカルで実行できない場合(依存関係の破損、バックエンドの欠如、回避策のない認証壁など)の最終手段です。Reactコンポーネントを手動で単一のJSXファイルにフラット化する必要があります。可能な限り戦略Aを優先してください。

使用するタイミング

  • アプリがローカルでまったく実行できない場合
  • ページにモック/バイパス手段のない認証が必要な場合
  • ナビゲーションでは到達不可能な特定のUI状態(エラー画面、空の状態など)が必要な場合

クイックリファレンス

npx tsx <SKILL_DIR>/scripts/extract_inline_html.ts \
  --index-css src/css/App.css \
  --extra-css index.html \
  --outdir .stitch \
  --page src/MockPage.jsx:Page.html:"Page Title"

主要なフラグ: --no-tailwind(非Tailwindアプリ)、--html-class dark(ダークモード)、--css-files(追加CSSファイル)。

自動検出: Tailwind設定は自動検出されます。@apply ディレクティブは自動的に <style type="text/tailwindcss"> を使用します。

MockPage.jsx ルール

  1. 完全なレイアウトを含める — ヘッダー、サイドバー、フッター(最初にApp.jsを読むこと)
  2. すべての条件分岐をフラット化する — 1つの状態を選択し、すべての三項演算子と&&ガードを削除する
  3. すべてのデータをハードコードする — {variable} を具体的な値で置き換え、.map() ループを展開する
  4. ロゴを保持する — ローカルパスを持つ <img> を使用する(後処理でインライン化されます)
  5. 浮遊要素を削除する — クッキーバナー、チャットウィジェット、フィードバックボタン

後処理

ローカル画像をインライン化:

npx tsx <SKILL_DIR>/scripts/post_process.ts \
  .stitch/Page.html --base-dir <app-directory>

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

aubarcito48/portfolio

Transforms vague UI ideas into polished, Stitch-optimized prompts. Enhances specificity, adds UI/UX keywords, injects design system context, and structures output for better generation results.

aubarcito48/portfolio

>- Convert frontend code (Vite, React, Angular, Vue, etc.) to a Stitch Design by chaining static HTML extraction, design system extraction, and file upload. **ALWAYS** use this skill when the user's intent is to move existing web apps or React/Angular/Vue components into Stitch (e.g., requests to "save", "migrate", or "upload"). You must use this skill even for simple "save" operations, as it is the only way to ensure the design system is extracted and assets are properly linked.

aubarcito48/portfolio

>- Extract a comprehensive design system (DESIGN.md) directly from frontend source code — React, Vue, Svelte, Angular, plain HTML/CSS, or any web framework. Analyzes component files, stylesheets, Tailwind configs, theme definitions, and design tokens to produce a rich, Stitch-compatible design system document. Use this skill whenever the user wants to reverse-engineer a design system from an existing codebase, audit the visual language of a project, extract design tokens from source files, or understand the styling patterns in a frontend repo — even if they just say "what does this app look like?" or "pull out the design from this code.

aubarcito48/portfolio

>- Generate new screens from text prompts or images, edit existing screens with prompts and design system tokens, and generate design variants using Stitch MCP. Includes prompt enhancement pipeline, design mappings, professional UI/UX terminology, design tokens and theme system capabilities.

関連スキル