web-design-harvester
web-design-harvester
レンダリング済みのWebページを、LLMが構築に使えるデザイン仕様に変換します。セクションごとのスクリーンショット、抽出・凝縮されたcomputed CSS、デザイントークン、レスポンシブ差分、そしてアルファチャンネルまで分析されたアセットを出力します。
Figma Sitesのページを再現するために作られましたが、Figma固有の機能は何も使っていません。レンダリングされるURLなら何でも動作します。
npm install
node bin/harvest.mjs https://example.figma.site --out ./spec --clean
# then point a model at ./spec/README.mdなぜこれを作ったのか
デザインの再現はかつてこうでした。Figmaでブロックを選択 → Copy all CSS → 2000行以上をチャットに貼り付ける → モデルが重要ないくつかの値を掘り起こす → 不一致のスクリーンショットを撮る → これを7〜8回繰り返す。
この工程のすべてのステップが機械的であり、しかも元の素材は見た目よりも質が悪いのです。FigmaのCSSエクスポートには、読めない負の座標を持つ回転フレーム、display: noneのプレースホルダーレイヤー、デスクトップとモバイルのバリアントが混在した状態が含まれています。
レンダリングされたDOMにはそうした問題は一切ありません。ライブページに対するgetComputedStyle()は、任意のブレークポイントにおける解決済みの真実であり、ネットワークのアセットリストも付いてきます。このツールはそれを読み取り、書き出します。
FigmaのREST APIは選択肢にならない
GET /v1/files/{key}は、editorType: "sites"または"make"のファイルに対して**400 "File type not supported by this endpoint"**を返します。読み取れるのはクラシックなdesignファイルだけです。抽出を計画する前に/v1/files/{key}/metaを確認してください。/metaと/stylesはすべてのタイプで動作しますが、ノードエンドポイントは動作しません。
ページをブラウザに表示させる
ここでつまずく人が多いので、正確に説明する価値があります。
対象 | 動作するか | 方法 |
公開サイト | ✅ はい | URLを渡すだけです。通常の公開ページです。 |
プレビューiframe | ❌ いいえ | 下記参照。 |
未公開サイト(自分のChromeで開いている) | ✅ はい |
|
その他のサイト、localhost、ステージング | ✅ はい | URLを渡すだけです。 |
プレビューiframeのURLは単体では動作しない
ページのように見えてHTTP 200を返しますが、取得するとpostMessageリスナーのみを含む約3.6KBのシェルが返ってきます。それ自体にはコンテンツがありません。
// what that URL actually serves, in full:
window.addEventListener('message', (e) => {
if (isAllowedOrigin(e.origin)) { // only figma.com and friends
if (e.data.type === 'iframe-init') {
script.src = e.data.initScriptURL // ← the real app comes from the parentサイトのコードは、ログイン済みのfigma.comタブからのMessagePort経由で届きます。URLを直接読み込むと、どれだけ待っても空白のドキュメントが返るだけです。提供すべきトークンも、設定すべきヘッダーもありません。コンテンツがそもそも存在しないのです。
未公開サイトの場合:自分のブラウザにアタッチする
リモートデバッグ付きでChromeを起動し、Figmaにログインしてサイトのプレビューを開き、ハーベスターをそのタブに向けます。
# 1. Chrome with a debugging port (use a separate profile to avoid clobbering yours)
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
--remote-debugging-port=9222 --user-data-dir=/tmp/figma-profile
# 2. Log into figma.com in that window, open your Sites file, hit Preview.
# 3. Harvest the rendered iframe
node bin/harvest.mjs "https://<uuid>-v2-figmaiframepreview.figma.site" \
--cdp 9222 --out ./spec--cdpを使うと、ツールはあなたのブラウザにアタッチし、何も起動・終了しません。より簡単な代替案(可能であれば)は、サイトを公開して公開URLを収穫することです。
毎回ログインをやり直したくないログイン必須のサイトには、--persistでプロファイルをディスクに保持できます。
使い方
harvest <url> [options] full harvest -> spec directory
harvest outline <url> print the DOM outline (recon)
harvest blocks <url> list blocks that would be captured
harvest asset <file...> analyse local media files
harvest serve [--port 8787] HTTP daemon, browser stays warm
harvest mcp MCP server on stdioオプション | デフォルト | 説明 | ||||
|
| 出力ディレクトリ | ||||
|
| ブレークポイント(例: |
| auto | ブロック境界を強制 | |
|
| ページ安定後の追加待機時間 | ||||
|
| ブロックあたりのノード上限 | ||||
| アセットのダウンロードと分析をスキップ | |||||
| 出力ディレクトリを先に消去 | |||||
| ブラウザウィンドウを表示 | |||||
| プロファイルを再利用しログインを維持 | |||||
| 実行中のChromeにアタッチ(ポートまたはws://URL) | |||||
| 機械可読なstdout |
見慣れないページではoutlineまたはblocksから始めてください。 これらは高速で、フル実行に踏み切る前に自動セグメンテーションが妥当なセクションを見つけられるかを教えてくれます。
node bin/harvest.mjs blocks https://figma.site --widths 1440strategy: semantic-landmarks
coverage: 100% (11248 of 11248px)
01 header.fig-suku18 1440×78 @0 [sticky] What you can do in figma
02 section.fig-lqoz33 1440×1109 @78 Figma Sites
03 section.fig-15ba1hq 1440×1117 @1187 Perfect websites every time…
…境界が正しくない場合は、--selector "main > section"を渡してください。
出力
spec/
README.md ← start here; index, warnings, token summary
index.json machine-readable manifest
tokens.md design tokens ranked by usage
tokens.css the same tokens as CSS custom properties
responsive.md every value that changes between breakpoints
interactions.md clickable/focusable elements and their transitions
warnings.json asset fit problems, in full
page-desktop.png full-page screenshot per breakpoint
page-mobile.png
blocks/
02-figma-sites/
block.md ← spec sheet for one section
desktop.png screenshot, exactly the block's size
mobile.png
tree.desktop.json exact computed values, full precision
tree.mobile.json
assets/
README.md every asset with content box and fit guidance
manifest.json
<files> deduplicated by content hashblock.mdは次のようになります。
section.fig-lqoz33 1440×1108.6 pad:0/0/32/0 relative bg:#ffffff
└─ div.fig-umtrpl 1440×1076.6 flex-col gap:64 pad:64/0/0/0
├─ h1.fig-6late5 660×72 mar:0/0/32/0 72/72 ls:-1.44 "Figma Sites"
└─ a.fig-1jz30fp 135×46.4 flex-row jc:center pad:12/22
#ffffff bg:#000000 r:8 href:/site/newさらに、ブレークポイントごとのジオメトリ、コピー、使用されたアセット、レスポンシブ差分テーブルが含まれます。隣接するJSONには、何かおかしい場合に備えて完全版の値が入っています。
スクリーンショットだけではできないこと
スクリーンショットは1 CSSピクセル = 1画像ピクセルです。 deviceScaleFactor: 1とscale: 'css'を組み合わせることで、PNGから測定した距離がそのままCSSピクセルになります。換算係数がないので、換算ミスもありません。(Figmaの@2xエクスポートでは、1440pxデザインに対して1798画像ピクセルが生成されるため、すべての測定値をまず1.2486で割る必要があり、これを間違えるともっともらしいが誤った数値が生まれました。)
Computedスタイルはダンプではなく蒸留されます。 すべての要素に対して3つのフィルターが実行されます。そのタグのUAデフォルトは除外され、親がすでに宣言している継承値は除外され、ほぼすべてのノードに現れる宣言(box-sizing: border-boxなど)は切り出されて一度だけ記述されます。残るのは差分だけであり、それが実際に書くべきものです。実際には、生のダンプよりおよそ1桁小さくなります。
アセットは推測ではなく測定されます。 すべての画像と動画について、ツールはフレームをデコードし、アルファチャンネルからコンテンツのバウンディングボックスを特定します。デザインアセットはしばしば1200×1200の正方形で、アートワークが中心からずれた1049×677の領域に収まっていることがあります。ファイルの寸法だけではこれは見えず、object-contain(余白ができる)もobject-cover+中央寄せ(軸がずれて切り取られる)も正しくありません。出力には使用すべきobject-positionが明記されます。
アルファ付きVP9 WebMは特別に処理されます。ffprobeはpix_fmt=yuv420pを報告しアルファチャンネルを表示しませんが、ブラウザは正しく合成します。アルファはlibvpx-vp9デコーダーを強制した場合にのみ現れます。
不可能なレイアウトは初回実行で指摘されます。 アセットのコンテンツ比率とそれが置かれているボックスが大きく食い違う場合、どのobject-fit値でも修正できません。アセットの再エクスポートが必要です。READMEはそれを即座にフラグし、coverが破棄するアートワークの割合も示します。CSSを調整してエクスポートの問題を修正しようと6ラウンドも費やすことはありません。
両方のブレークポイント。仕様の半分は差分にあるからです。 カードの角丸12px → 6px、タイトル20/30 → 16/24、ヘッダーのパディング32px → 32px(変更なし)。これらはどれもスケーリングでは導出できません。responsive.mdは変化するすべての値を列挙します。
任意の数のブレークポイント。 --widths 1440,768,375で3つ取得でき、すべてがそれに応じて拡張されます。ブレークポイントごとのスクリーンショットとスタイルツリー、tokens.mdでのブレークポイント別の使用回数、そして各隣接ペアの差分テーブル — desktop → tablet、次にtablet → mobileです。すべてをデスクトップと比較するのではなく隣接比較にするのは、メディアクエリの書き方を反映しているからです。各ステップは前のステップから変更された点だけを言い直します。responsive.mdは、どのブロックがどのステップで変化するかのマトリックスで始まります。
何も黙って破棄されません。 セグメンテーション後、ツールはブロックがページを隙間なく覆っているかを確認し、隙間を覆う要素を探し、カバレッジ比率を報告します。本当に取得できない領域は無視するのではなく列挙されます。スクリーンショットの寸法は要求されたものと照合されます。切り詰められたキャプチャは失敗したものより悪いからです。見た目は正常で、そこから測定したすべての値が静かに間違っているからです。
モデルへの提供
コールドランはほとんどの時間をブラウザ起動と初回ペイントに費やします。モデルが反復している場合 — あのブロックをもう一度、今度は768pxで、あのアイコンの色は何色か — 質問ごとにそのコストを払うとツールは使い物になりません。両方のサーバーモードはブラウザと読み込み済みページを温かい状態に保ちます。
https://figma.siteでの測定値: コールド26.8秒 → ウォーム0.03秒。
MCP(stdio)
{
"mcpServers": {
"web-design-harvester": {
"command": "node",
"args": ["/absolute/path/to/web-design-harvester/bin/harvest.mjs", "mcp"]
}
}
}ツール: harvest_outline、harvest_blocks、harvest_block、harvest_tokens、harvest_assets、harvest_screenshot、harvest_analyse_asset、harvest_site、harvest_status。
典型的なループは、harvest_blocksでセクションを見つけ、次にharvest_blockでその構造を取得するというものです。2回目の呼び出しはページがすでに開いているため、数十ミリ秒で完了します。
HTTPデーモン
node bin/harvest.mjs serve --port 8787
curl "http://127.0.0.1:8787/blocks?url=https://figma.site&width=1440"
curl "http://127.0.0.1:8787/block?url=https://figma.site&index=4"ループバックのみにバインドします。任意のURLを取得して指定された場所にファイルを書き込むため、外部から到達可能であってはなりません。本当に必要な場合のみ--hostを渡してください。アイドル状態のページは10分後に閉じられます。
要件
Node 18以上
Playwright Chromium —
npm installがpostinstallフック経由で取得しますffmpeg / ffprobe (任意) — コンテンツボックス、パレット、動画分析に必要です。これがなくても他の機能はすべて動作します。アセットのインテリジェンスは警告付きでスキップされます。
brew install ffmpeg
npm test # 46 tests, ~10s, hermetic (local fixture, no network)既知の制限
クロスオリジンiframeはDOMとスクリーンショットの両方で穴になります。ツールはそれらを検出し、サイズ・オリジン・
srcをblock.mdに列挙しますが、内部は見えません。フレームがレンダリングするものは別途処理する必要があります。ホバーとフォーカスのスタイルは取得されません。ライブな操作が必要だからです。
interactions.mdは各要素のtransitionプロパティと時間を示し、何がどの速さでアニメーションするかはわかりますが、最終状態はわかりません。ストリーミング動画(DASH/fMP4)は単体では有効でないセグメントとして届きます。これらは破損として報告するのではなく、そのようにラベル付けされます。
CanvasとWebGLのコンテンツはスクリーンショット内のピクセルとして取得されます。抽出できる構造はありません。
スクロール駆動アニメーションは1時点でサンプリングされます。ページはまず端から端までスクロールされて出現をトリガーし、その後先頭に戻ります。スクロール位置に依存して出現するセクションは、最終状態にない可能性があります。
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Turn any live website into brand colors, fonts, design tokens, SVGs, Lottie and paste-ready code.
UI design from prompts, screenshots, and URLs for AI coding agents and theme tokens.
Score any URL against a real design contract — 40 checks, A-F grade, token + motion validation.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ChenYCL/web-design-harvester'
If you have feedback or need assistance with the MCP directory API, please join our Discord server