clone-website について
Clone Websiteは、ウェブサイトを調査し、Next.jsプロジェクトでの視覚的な再構築を進めるスキルです。ページの外観、素材、レスポンシブレイアウト、操作をコンポーネント仕様にまとめ、ビルダーエージェントに渡します。
主な機能
- 01ブラウザー自動化によるサイト調査
- 02デスクトップ・モバイル画面の撮影
- 03スタイル・テキスト・素材の抽出
- 04操作状態と挙動の記録
- 05ビルダーエージェント向け仕様の作成
- 06TypeScriptとビルドの検証
活用シーン
- 01公開URLをもとにしたページ再構築
- 02レスポンシブ設計と操作の記録
- 03監査可能なコンポーネント実装指示の準備
MCP 対応
対象ページの調査には、Chrome MCPやPlaywright MCPなどのブラウザーMCPツールが必要です。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ julianromli/ ai-skills --skill clone-websiteインストール後、Claude Code で/clone-websiteを入力して読み込まれたか確認します。
詳細
ウェブサイトのクローン作成
これから $ARGUMENTS をリバースエンジニアリングし、ピクセル単位で完全に一致するクローンを作成します。
複数の URL が指定された場合は、可能な限りそれぞれを独立して並行処理し、各サイトの抽出成果物は専用フォルダー(例:docs/research/<hostname>/)に分けて保管してください。
これは「調査してから構築する」という二段階のプロセスではありません。あなたは現場を回る現場監督です。ページの各セクションを調査しながら、詳細な仕様をファイルに書き出し、必要な情報をすべて添えて専門のビルダーエージェントに渡します。抽出と構築は並行して進めますが、抽出は綿密に行い、監査可能な成果物を作成します。
デフォルトの範囲
対象は $ARGUMENTS が示すページです。その URL で表示される内容を正確にクローンしてください。ユーザーから別途指定がない限り、次のデフォルトを使用します。
- 忠実度: ピクセル単位で完全に一致 — 色、間隔、タイポグラフィ、アニメーションを正確に再現
- 対象範囲: 視覚的なレイアウトとスタイル、コンポーネントの構造とインタラクション、レスポンシブデザイン、デモ用のモックデータ
- 対象外: 実際のバックエンド/データベース、認証、リアルタイム機能、SEO 最適化、アクセシビリティ監査
- カスタマイズ: なし — 純粋なエミュレーション
ユーザーから追加の指示(忠実度の指定、カスタマイズ、追加のコンテキストなど)があれば、デフォルトよりもそちらを優先してください。
事前確認
- ブラウザー自動化は必須です。 利用可能なブラウザー MCP ツール(Chrome MCP、Playwright MCP、Browserbase MCP、Puppeteer MCP など)を確認してください。利用できるものを使用し、複数ある場合は Chrome MCP を優先してください。何も検出されない場合は、ユーザーに使用しているブラウザーツールと接続方法を確認してください。このスキルはブラウザー自動化なしでは機能しません。
$ARGUMENTSを 1 つ以上の URL として解析します。各 URL を正規化して検証し、無効な URL があれば、作業を進める前に修正を依頼してください。有効な URL ごとに、ブラウザー MCP ツールでアクセス可能か確認します。- ベースプロジェクトがビルドできることを確認します:
npm run build。Next.js + shadcn/ui + Tailwind v4 のひな型がすでに用意されている必要があります。用意されていない場合は、先にセットアップするようユーザーに伝えてください。 - 存在しない場合は、出力ディレクトリーを作成します:
docs/research/、docs/research/components/、docs/design-references/、scripts/。複数のクローンを作成する場合は、docs/research/<hostname>/やdocs/design-references/<hostname>/のようなサイトごとのフォルダーも用意します。 - 1 回のコマンドで複数のサイトを作業する場合、リソースに余裕があれば並行して実行するか、過負荷を避けるために順次実行するかを、必要に応じて確認してください(並行実行を推奨)。
指針
これらは、クローンの出来栄えを「まあまあ」で済ませるか、成功に導くかを左右する原則です。内容をしっかり理解し、すべての判断に反映してください。
1. 速さより完全性
各ビルダーエージェントには、作業を完璧に行うために必要なものをすべて渡してください。スクリーンショット、正確な CSS 値、ローカルパス付きのダウンロード済みアセット、実際のテキストコンテンツ、コンポーネント構造が必要です。色、フォントサイズ、パディングなど、ビルダーに推測させることがあれば、抽出が不十分だったということです。不完全な指示書を渡すくらいなら、もう 1 分かけて追加のプロパティを 1 つ抽出してください。
2. 小さなタスクで完璧な結果を
エージェントに「機能セクション全体を構築して」と依頼すると、細部を見落とし、余白をおおよそで済ませたり、フォントサイズを推測したりして、「それなり」ではあるものの明らかに間違ったものを作ってしまいます。一方、正確な CSS 値を指定した、焦点を絞った単一コンポーネントを依頼すれば、毎回見事に仕上げます。
各セクションを見て、その複雑さを判断してください。見出しとボタンのシンプルなバナーなら、エージェントは 1 つで十分です。異なるホバーステートと内部レイアウトを持つカードが 3 種類ある複雑なセクションなら、カードの種類ごとに 1 つずつ、さらにセクションのラッパー用に 1 つのエージェントを割り当てます。迷ったら、より小さく分けてください。
複雑さの予算ルール: ビルダー向けプロンプトが仕様の内容で約 150 行を超える場合、そのセクションは 1 つのエージェントには複雑すぎます。小さなパーツに分割してください。「でも全部関連しているから」といって、この機械的なチェックを無視してはいけません。
3. 実際のコンテンツとアセットを使う
実際のサイトから、テキスト、画像、動画、SVG を抽出してください。これはクローンであり、モックアップではありません。element.textContent を使い、すべての <img> と <video> をダウンロードし、インラインの <svg> 要素は React コンポーネントとして抽出してください。コンテンツを生成するのは、サーバーが生成していて、セッションごとに明らかに異なる場合に限ります。
レイヤー化されたアセットも重要です。 1 枚の画像に見えるセクションも、複数のレイヤーで構成されていることがよくあります。背景の水彩画/グラデーション、前景の UI モックアップ PNG、オーバーレイアイコンなどです。各コンテナーの DOM ツリー全体を調べ、絶対配置のオーバーレイも含めて、その中にあるすべての <img> 要素と背景画像を列挙してください。背景が正しくても、オーバーレイ画像を見落とすと、クローンは空っぽに見えてしまいます。
4. まず基盤を整える
基盤が整うまで、何も構築できません。対象サイトのデザイントークン(色、フォント、余白)を含むグローバル CSS、コンテンツ構造の TypeScript 型、そしてグローバルアセット(フォント、ファビコン)が必要です。この工程は順序どおりに進める必要があり、省略できません。これ以降の作業はすべて並行して進められます。
5. 見た目と動作の両方を抽出する
ウェブサイトはスクリーンショットではなく、生きたものです。スクロール、ホバー、クリック、サイズ変更、時間の経過に応じて、要素は動き、変化し、現れたり消えたりします。各要素の静的な CSS だけを抽出すると、スクリーンショットでは正しく見えても、実際に使うときには生気のないクローンになってしまいます。
すべての要素について、見た目(getComputedStyle() で取得する正確な計算済み CSS)と動作(何が変化し、何がその変化を引き起こし、どのように遷移するか)の両方を抽出してください。「16px くらいに見える」ではなく、実際の計算済みの値を抽出してください。「スクロールするとナビが変わる」ではなく、正確なトリガー(スクロール位置、IntersectionObserver のしきい値、ビューポートとの交差)、変化前と変化後の状態(両方の CSS 値一式)、遷移(duration、easing、CSS transition・JS による制御・CSS animation-timeline のどれか)を記録してください。
次に挙げるのは、注目すべき動作の例です。網羅的な一覧ではありません。ページにはこの一覧にない動作もあるため、それらも必ず見つけてください。
- スクロールがしきい値を超えると、小さくなったり、背景が変わったり、影が付いたりするナビゲーションバー
- ビューポートに入るとアニメーション表示される要素(フェードアップ、スライドイン、段階的な遅延)
- スクロール時に位置を合わせて止まるセクション(
scroll-snap-type) - スクロールとは異なる速度で動く視差レイヤー
- アニメーションするホバーステート(単に変化するだけではなく、遷移時間とイージングも重要です)
- 表示/非表示アニメーション付きのドロップダウン、モーダル、アコーディオン
- スクロールに連動する進捗インジケーターや不透明度の遷移
- 自動再生するカルーセルや、切り替わるコンテンツ
- ページのセクション間で切り替わる、ダークからライトへのテーマ(またはその他のテーマ)の遷移
- 切り替わるタブ/ピル型コンテンツ — 遷移アニメーション付きで、表示されるカードのセットを切り替えるボタン
- スクロールに連動するタブ/アコーディオンの切り替え — コンテンツがスクロールして通過すると、サイドバーのアクティブ項目が自動で変わるもの(クリックハンドラーではなく、IntersectionObserver を使用)
- スムーズスクロールライブラリ(Lenis、Locomotive Scroll)—
.lenisクラスやスクロールコンテナーのラッパーがないか確認する
6. 構築前にインタラクションモデルを特定する
クローン作成で最もコストのかかる失敗は、スクロール操作が中心の UI をクリック操作が中心の UI として、あるいはその逆として構築してしまうことです。インタラクティブなセクション用のビルダープロンプトを書く前に、必ず次の問いに明確な答えを出してください。このセクションを動かすのは、クリック、スクロール、ホバー、時間、またはそれらの組み合わせのどれですか?
特定する方法:
- 最初にクリックしないでください。 セクションをゆっくりスクロールし、スクロールに応じて要素が自動的に変化するか観察します。
- 変化する場合は、スクロール連動です。仕組みを特定します。
IntersectionObserver、scroll-snap、position: sticky、animation-timeline、または JS のスクロールリスナーなどです。 - スクロールしても何も変化しない場合は、その後でクリック/ホバーを試し、クリック/ホバー連動のインタラクションかどうか確認します。
- コンポーネント仕様にインタラクションモデルを明記します。「INTERACTION MODEL: IntersectionObserver によるスクロール連動」や「INTERACTION MODEL: 不透明度遷移によるクリック切り替え」のように記述します。
スティッキーなサイドバーとスクロールするコンテンツパネルで構成されるセクションは、クリックしてコンテンツを切り替えるタブインターフェースとは根本的に異なります。これを誤ると、CSS の微調整では済まず、全面的な書き直しが必要になります。
7. デフォルトだけでなく、すべての状態を抽出する
多くのコンポーネントには複数の視覚状態があります。タブバーはタブごとに異なるカードを表示し、ヘッダーはスクロール位置が 0 のときと 100 のときで見た目が異なり、カードにはホバー効果があります。ページ読み込み時に見える状態だけでなく、すべての状態を抽出してください。
タブ切り替え/状態を持つコンテンツの場合:
- ブラウザー MCP で各タブ/ボタンをクリックします
- 各状態のコンテンツ、画像、カードデータを抽出します
- どのコンテンツがどの状態に属するかを記録します
- 状態間の遷移アニメーション(不透明度、スライド、フェードなど)を記録します
スクロール依存の要素の場合:
- スクロール位置 0(初期状態)で計算済みスタイルを取得します
- トリガーのしきい値を超えてスクロールし、計算済みスタイルを再度取得します(スクロール後の状態)
- 2 つを比較し、変化する CSS プロパティを正確に特定します
- 遷移 CSS(時間、イージング、プロパティ)を記録します
- 正確なトリガーしきい値(スクロール位置の px 値、またはビューポートとの交差率)を記録します
8. 仕様ファイルを信頼できる唯一の情報源にする
ビルダーを起動する前に、すべてのコンポーネントについて docs/research/components/ に仕様ファイルを作成します。このファイルは、抽出作業とビルダーの間の取り決めです。ビルダーにはプロンプト内に仕様ファイルの内容を直接渡します。また、このファイルは監査可能な成果物として残るため、問題があるように見える場合にユーザー(またはあなた)が確認できます。
仕様ファイルは任意ではありません。あれば望ましいというものでもありません。仕様ファイルを作成せずにビルダーを起動するということは、ブラウザー MCP セッションで覚えている内容だけを頼りに不完全な指示を出すことであり、不明点をビルダーが推測で補うことになります。
9. ビルドは必ず成功させる
すべてのビルダーエージェントは、完了前に npx tsc --noEmit が成功することを確認する必要があります。ワークツリーをマージした後は、npm run build が成功することを確認します。一時的であっても、ビルドが壊れた状態は決して許容されません。
フェーズ 1:事前調査
ブラウザー MCP で対象の URL に移動します。
スクリーンショット
- デスクトップ(1440px)とモバイル(390px)のビューポートで、ページ全体のスクリーンショットを撮影します
- 説明的な名前を付けて
docs/design-references/に保存します - これらを基準資料とします。後ほどビルダーには、セクションごとに切り抜いたスクリーンショットを渡します
全体の抽出
作業を始める前に、ページから以下を抽出します。
フォント — <link> タグで Google Fonts またはセルフホストフォントを確認します。主要な要素(見出し、本文、コード、ラベル)の計算済み font-family を確認します。実際に使用されているすべてのファミリー、ウェイト、スタイルを記録します。next/font/google または next/font/local を使用して、src/app/layout.tsx で設定します。
色 — ページ全体の計算済みスタイルから、サイトのカラーパレットを抽出します。src/app/globals.css の :root および .dark の CSS 変数ブロックを、対象サイトで実際に使われている色に更新します。適合するものは shadcn のトークン名(background、foreground、primary、muted など)に割り当てます。shadcn のトークンに対応しない色には、カスタムプロパティを追加します。
ファビコンとメタデータ — ファビコン、apple-touch-icon、OG 画像、webmanifest を public/seo/ にダウンロードします。layout.tsx のメタデータを更新します。
全体的な UI パターン — サイト全体に適用される CSS や JS を特定します。カスタムのスクロールバー非表示、ページコンテナの scroll-snap、グローバルなキーフレームアニメーション、バックドロップフィルター、オーバーレイとして使用されるグラデーション、スムーズスクロールライブラリ(Lenis、Locomotive Scroll — .lenis、.locomotive-scroll、カスタムスクロールコンテナのクラスを確認)などを調べます。これらを globals.css に追加し、インストールが必要なライブラリを記録します。
必須のインタラクション確認
これはスクリーンショットの撮影後、ほかの作業に入る前に行う専用の確認工程です。目的は、静的なスクリーンショットでは見えないものも含め、ページ上のあらゆる動作を把握することです。
スクロール確認: ブラウザー MCP を使い、ページを上から下までゆっくりスクロールします。各セクションで一時停止して、次の点を確認します。
- ヘッダーの見た目が変化するか。変化する場合は、その位置を記録します。
- 要素が画面内に入るとアニメーションするか。対象の要素とアニメーションの種類を記録します。
- スクロールに合わせてサイドバーやタブのインジケーターが自動で切り替わるか。切り替えの仕組みを記録します。
- scroll-snap の位置があるか。ある場合は、対象のコンテナを記録します。
- スムーズスクロールライブラリが有効か。ネイティブではないスクロール動作がないか確認します。
クリック確認: インタラクティブに見える要素をすべてクリックします。
- すべてのボタン、タブ、ピル、リンク、カード
- 起きた動作を記録します。コンテンツが変わるか、モーダルが開くか、ドロップダウンが表示されるかなどを確認します。
- タブやピルはそれぞれをクリックし、各状態で表示されるコンテンツを記録します。
ホバー確認: ホバー状態がありそうな要素すべてにカーソルを合わせます。
- ボタン、カード、リンク、画像、ナビゲーション項目
- 変化する内容を記録します。色、拡大・縮小、影、下線、不透明度などを確認します。
レスポンシブ確認: ブラウザー MCP を使い、次の3つのビューポート幅でテストします。
- デスクトップ:1440px
- タブレット:768px
- モバイル:390px
- 各幅で、レイアウトが変わるセクション(列から縦積みになる、サイドバーが非表示になるなど)と、切り替わるおおよそのブレークポイントを記録します。
確認した内容はすべて docs/research/BEHAVIORS.md に保存します。これは動作仕様の基準資料です。各コンポーネントの仕様を作成する際に参照してください。
ページ構成
ページ上の各セクションを上から下へ洗い出します。それぞれに仮の名前を付け、以下を記録します。
- 表示順
- 固定/スティッキーなオーバーレイか、通常のフローコンテンツか
- ページ全体のレイアウト(スクロールコンテナ、列構成、z-index のレイヤー)
- セクション間の依存関係(すべてのコンテンツに重なるフローティングナビゲーションなど)
- 各セクションのインタラクションモデル(静的、クリック駆動、スクロール駆動、時間駆動)
docs/research/PAGE_TOPOLOGY.md に保存します。これはページを組み立てるための設計図になります。
フェーズ 2:基盤の構築
この作業は順番に進めます。多くのファイルに関わるため、エージェントに委任せず、自分で行ってください。
layout.tsxのフォントを、対象サイトで実際に使われているフォントに合わせて更新しますglobals.cssに、対象サイトのカラー トークン、間隔の値、キーフレームアニメーション、ユーティリティクラス、およびグローバルなスクロール動作(Lenis、スムーズスクロールの CSS、body の scroll-snap)を反映します- 確認したコンテンツ構造に基づいて、
src/types/に TypeScript インターフェースを作成します - SVG アイコンを抽出します。ページ上のインライン
<svg>要素をすべて見つけ、重複を除外して、src/components/icons.tsxに名前付きの React コンポーネントとして保存します。視覚的な機能に基づいて名前を付けてください(例:SearchIcon、ArrowRightIcon、LogoIcon)。 - グローバルアセットをダウンロードします。ページ上の画像、動画、その他のバイナリアセットをすべて
public/にダウンロードする Node.js スクリプト(scripts/download-assets.mjs)を作成して実行します。意味のあるディレクトリ構造を維持してください。 - 検証します:
npm run buildが成功すること
アセット検出スクリプトのパターン
ブラウザー MCP を使って、ページ上のすべてのアセットを列挙します。
// Run this via browser MCP to discover all assets
JSON.stringify({
images: [...document.querySelectorAll('img')].map(img => ({
src: img.src || img.currentSrc,
alt: img.alt,
width: img.naturalWidth,
height: img.naturalHeight,
// Include parent info to detect layered compositions
parentClasses: img.parentElement?.className,
siblings: img.parentElement ? [...img.parentElement.querySelectorAll('img')].length : 0,
position: getComputedStyle(img).position,
zIndex: getComputedStyle(img).zIndex
})),
videos: [...document.querySelectorAll('video')].map(v => ({
src: v.src || v.querySelector('source')?.src,
poster: v.poster,
autoplay: v.autoplay,
loop: v.loop,
muted: v.muted
})),
backgroundImages: [...document.querySelectorAll('*')].filter(el => {
const bg = getComputedStyle(el).backgroundImage;
return bg && bg !== 'none';
}).map(el => ({
url: getComputedStyle(el).backgroundImage,
element: el.tagName + '.' + el.className?.split(' ')[0]
})),
svgCount: document.querySelectorAll('svg').length,
fonts: [...new Set([...document.querySelectorAll('*')].slice(0, 200).map(el => getComputedStyle(el).fontFamily))],
favicons: [...document.querySelectorAll('link[rel*="icon"]')].map(l => ({ href: l.href, sizes: l.sizes?.toString() }))
});
次に、すべてを public/ に取得するダウンロードスクリプトを作成します。適切なエラー処理を行い、4 件ずつ並列でダウンロードしてください。
フェーズ 3:コンポーネント仕様と割り当て
これが中心となる反復作業です。ページ構成内の各セクションについて、上から順に、抽出、仕様ファイルの作成、ビルダーへの割り当ての 3 つを行います。
ステップ 1:抽出
各セクションについて、ブラウザー MCP を使ってすべてを抽出します。
-
セクションだけを表示した状態のスクリーンショットを撮影します(セクションまでスクロールし、表示領域を撮影)。
docs/design-references/に保存します。 -
セクション内のすべての要素の CSS を抽出します。以下の抽出スクリプトを使い、個々のプロパティを手作業で測定しないでください。コンポーネントのコンテナごとに 1 回実行し、出力全体を記録します。
// Per-component extraction — run via browser MCP
// Replace SELECTOR with the actual CSS selector for the component
(function(selector) {
const el = document.querySelector(selector);
if (!el) return JSON.stringify({ error: 'Element not found: ' + selector });
const props = [
'fontSize','fontWeight','fontFamily','lineHeight','letterSpacing','color',
'textTransform','textDecoration','backgroundColor','background',
'padding','paddingTop','paddingRight','paddingBottom','paddingLeft',
'margin','marginTop','marginRight','marginBottom','marginLeft',
'width','height','maxWidth','minWidth','maxHeight','minHeight',
'display','flexDirection','justifyContent','alignItems','gap',
'gridTemplateColumns','gridTemplateRows',
'borderRadius','border','borderTop','borderBottom','borderLeft','borderRight',
'boxShadow','overflow','overflowX','overflowY',
'position','top','right','bottom','left','zIndex',
'opacity','transform','transition','cursor',
'objectFit','objectPosition','mixBlendMode','filter','backdropFilter',
'whiteSpace','textOverflow','WebkitLineClamp'
];
function extractStyles(element) {
const cs = getComputedStyle(element);
const styles = {};
props.forEach(p => { const v = cs[p]; if (v && v !== 'none' && v !== 'normal' && v !== 'auto' && v !== '0px' && v !== 'rgba(0, 0, 0, 0)') styles[p] = v; });
return styles;
}
function walk(element, depth) {
if (depth > 4) return null;
const children = [...element.children];
return {
tag: element.tagName.toLowerCase(),
classes: element.className?.toString().split(' ').slice(0, 5).join(' '),
text: element.childNodes.length === 1 && element.childNodes[0].nodeType === 3 ? element.textContent.trim().slice(0, 200) : null,
styles: extractStyles(element),
images: element.tagName === 'IMG' ? { src: element.src, alt: element.alt, naturalWidth: element.naturalWidth, naturalHeight: element.naturalHeight } : null,
childCount: children.length,
children: children.slice(0, 20).map(c => walk(c, depth + 1)).filter(Boolean)
};
}
return JSON.stringify(walk(el, 0), null, 2);
})('SELECTOR');
- 複数状態のスタイルを抽出します。スクロールに連動する状態、ホバー状態、アクティブなタブなど、複数の状態がある要素について、両方の状態を記録します。
// State A: capture styles at current state (e.g., scroll position 0)
// Then trigger the state change (scroll, click, hover via browser MCP)
// State B: re-run the extraction script on the same element
// The diff between A and B IS the behavior specification
差分を明確に記録します:「プロパティ X は、トリガー TRIGGER によって VALUE_A から VALUE_B に変化し、transition: TRANSITION_CSS が適用されます。」
-
実際のコンテンツを抽出します。すべてのテキスト、alt 属性、aria ラベル、プレースホルダーテキストを取得します。各テキストノードには
element.textContentを使ってください。タブ切り替え式や状態を持つコンテンツでは、各タブをクリックして状態ごとにコンテンツを抽出します。 -
このセクションで使用するアセットを特定します。
public/にダウンロードした画像や動画、icons.tsxのアイコンコンポーネントを確認します。同じコンテナ内に複数の<img>または背景画像が重なっているレイヤー画像がないか確認してください。 -
複雑さを評価します。このセクションには、独立したサブコンポーネントがいくつありますか?独立したサブコンポーネントとは、カード、ナビゲーション項目、検索パネルなど、独自のスタイル、構造、動作を持つ要素です。
ステップ 2:コンポーネント仕様ファイルを作成
各セクションについて(または分割する場合は各サブコンポーネントについて)、docs/research/components/ に仕様ファイルを作成します。これは省略できません。すべてのビルダーに対応する仕様ファイルが必要です。
ファイルパス: docs/research/components/<component-name>.spec.md
テンプレート:
# <ComponentName> Specification
## Overview
- **Target file:** `src/components/<ComponentName>.tsx`
- **Screenshot:** `docs/design-references/<screenshot-name>.png`
- **Interaction model:** <static | click-driven | scroll-driven | time-driven>
## DOM Structure
<Describe the element hierarchy — what contains what>
## Computed Styles (exact values from getComputedStyle)
### Container
- display: ...
- padding: ...
- maxWidth: ...
- (every relevant property with exact values)
### <Child element 1>
- fontSize: ...
- color: ...
- (every relevant property)
### <Child element N>
...
## States & Behaviors
### <Behavior name, e.g., "Scroll-triggered floating mode">
- **Trigger:** <exact mechanism — scroll position 50px, IntersectionObserver rootMargin "-30% 0px", click on .tab-button, hover>
- **State A (before):** maxWidth: 100vw, boxShadow: none, borderRadius: 0
- **State B (after):** maxWidth: 1200px, boxShadow: 0 4px 20px rgba(0,0,0,0.1), borderRadius: 16px
- **Transition:** transition: all 0.3s ease
- **Implementation approach:** <CSS transition + scroll listener | IntersectionObserver | CSS animation-timeline | etc.>
### Hover states
- **<Element>:** <property>: <before> → <after>, transition: <value>
## Per-State Content (if applicable)
### State: "Featured"
- Title: "..."
- Subtitle: "..."
- Cards: [{ title, description, image, link }, ...]
### State: "Productivity"
- Title: "..."
- Cards: [...]
## Assets
- Background image: `public/images/<file>.webp`
- Overlay image: `public/images/<file>.png`
- Icons used: <ArrowIcon>, <SearchIcon> from icons.tsx
## Text Content (verbatim)
<All text content, copy-pasted from the live site>
## Responsive Behavior
- **Desktop (1440px):** <layout description>
- **Tablet (768px):** <what changes — e.g., "maintains 2-column, gap reduces to 16px">
- **Mobile (390px):** <what changes — e.g., "stacks to single column, images full-width">
- **Breakpoint:** layout switches at ~<N>px
すべてのセクションを埋めてください。該当しないセクション(静的なフッターに状態がない場合など)には「該当なし」と記入します。ただし、「状態と動作」を「該当なし」とする前によく考えてください。フッターであっても、リンクにホバー状態がある場合があります。
Step 3: ビルダーを割り当てる
複雑さに応じて、ビルダーエージェントを作業ツリーに割り当てます。
シンプルなセクション(サブコンポーネントが1~2個):1つのビルダーエージェントがセクション全体を担当します。
複雑なセクション(異なるサブコンポーネントが3個以上):分割します。サブコンポーネントごとに1つのエージェントを割り当て、さらに、それらをインポートするセクションラッパー用に1つのエージェントを割り当てます。ラッパーはサブコンポーネントに依存するため、サブコンポーネントのビルダーが先に作業します。
すべてのビルダーエージェントに渡すもの:
- 担当コンポーネントの仕様ファイルの全文(プロンプトにインラインで含めます。「仕様ファイルを読んで」と指示しないでください)
docs/design-references/内のセクションのスクリーンショットへのパス- インポートする共有コンポーネント(
icons.tsx、cn()、shadcn プリミティブ) - 対象ファイルのパス(例:
src/components/HeroSection.tsx) - 完了前に
npx tsc --noEmitで検証するよう指示 - レスポンシブ動作については、具体的なブレークポイント値と変更内容
待たないでください。 あるセクションのビルダーを割り当てたら、次のセクションの抽出に進みます。抽出を続けている間、ビルダーは作業ツリーで並行して作業します。
Step 4: マージ
ビルダーエージェントが作業を終えたら、次の手順で進めます。
- 作業ツリーのブランチを main にマージします
- 各エージェントが何を構築したかをすべて把握しているため、競合があれば適切に解決します
- マージのたびに
npm run buildを実行し、ビルドが引き続き成功することを確認します - マージによって型エラーが発生した場合は、直ちに修正します
すべてのセクションが構築されるまで、抽出 → 仕様作成 → 割り当て → マージのサイクルを続けます。
Phase 4: ページの組み立て
すべてのセクションを構築してマージしたら、src/app/page.tsx ですべてを接続します。
- すべてのセクションコンポーネントをインポートします
- トポロジー文書に基づいてページレベルのレイアウトを実装します(スクロールコンテナー、カラム構造、スティッキー配置、z-index のレイヤー構成)
- 実際のコンテンツをコンポーネントの props に接続します
- ページレベルの動作を実装します:スクロールスナップ、スクロール連動アニメーション、ダークからライトへの切り替え、インターセクションオブザーバー、スムーススクロール(Lenis など)
- 検証します:
npm run buildがエラーなく成功すること
Phase 5: ビジュアル QA の差分確認
組み立てが完了しても、クローンの完成を宣言してはいけません。並べて比較するスクリーンショットを撮影します。
- 元のサイトとクローンを並べて開くか、同じビューポート幅でスクリーンショットを撮影します
- デスクトップ(1440px)で、上から下へセクションごとに比較します
- モバイル(390px)でもう一度比較します
- 見つかった不一致ごとに、次の手順を実行します。
- コンポーネント仕様ファイルを確認します。値の抽出は正確でしたか?
- 仕様が誤っていた場合:ブラウザー MCP から再抽出し、仕様を更新して、コンポーネントを修正します
- 仕様は正しかったがビルダーが誤った場合:仕様に一致するようコンポーネントを修正します
- すべてのインタラクティブな動作をテストします。ページをスクロールし、すべてのボタンとタブをクリックし、インタラクティブな要素にマウスオーバーします
- スムーススクロールの操作感、ヘッダーの切り替え、タブの切り替え、アニメーションの再生を確認します
このビジュアル QA を通過して初めて、クローンは完成です。
割り当て前のチェックリスト
ビルダーエージェントを割り当てる前に、すべての項目にチェックを付けられることを確認してください。できない項目があれば、戻ってさらに情報を抽出してください。
- 仕様ファイルが
docs/research/components/<name>.spec.mdに作成され、すべてのセクションが記入されている - 仕様に記載されたすべての CSS 値が推定値ではなく、
getComputedStyle()から取得されている - インタラクションモデルが特定され、文書化されている(静的/クリック/スクロール/時間)
- 状態を持つコンポーネントについて、すべての状態のコンテンツとスタイルが記録されている
- スクロール連動コンポーネントについて、トリガーのしきい値、前後のスタイル、遷移が記録されている
- ホバー状態について、前後の値と遷移のタイミングが記録されている
- セクション内のすべての画像が特定されている(オーバーレイやレイヤー構成も含む)
- デスクトップとモバイルを含め、レスポンシブ動作が文書化されている
- テキストコンテンツが言い換えられず、サイトからそのまま転記されている
- ビルダーへのプロンプトが仕様約150行以内である。超える場合は、セクションを分割する必要がある
やってはいけないこと
これらは、過去に失敗したクローンから得られた教訓です。それぞれ、何時間もの手戻りにつながりました。
- 元のサイトがスクロール操作に連動するのに、クリック式のタブを作らないでください(またはその逆)。 クリックする前にスクロールして、まず操作モデルを確認してください。これは最も大きな手戻りを招く間違いです。CSS の修正では済まず、全面的な書き直しが必要になります。
- 初期状態だけを抽出しないでください。 読み込み時に「Featured」と表示されるタブがある場合は、「Productivity」「Creative」「Lifestyle」をクリックし、それぞれのカードやコンテンツを抽出してください。スクロール時にヘッダーが変わる場合は、スクロール位置 0 と 100 以上の両方でスタイルを記録してください。
- 重なり合う画像やレイヤー画像を見落とさないでください。 背景の水彩画と前景の UI モックアップがある場合、画像は 2 枚です。各コンテナーの DOM ツリーを確認し、複数の
<img>要素や位置指定されたオーバーレイがないか調べてください。 - 実際には動画やアニメーションであるコンテンツに、モックアップコンポーネントを作らないでください。 動画に表示される内容を手の込んだ HTML モックアップで再現する前に、そのセクションで
<video>、Lottie、canvas のどれが使われているか確認してください。 - CSS クラスをおおよそで済ませないでください。 「
text-lgに見える」と判断しても、計算値が18pxで、text-lgが18px/28pxなのに、実際の line-height が24pxなら正しくありません。正確な値を抽出してください。 - すべてを 1 つの巨大なコミットにまとめないでください。 このパイプラインの目的は、各段階でビルドを検証しながら、段階的に進めることです。
- ビルダーへのプロンプトでドキュメントを参照させないでください。 各ビルダーのプロンプトには CSS 仕様を直接記載してください。「色については DESIGN_TOKENS.md を参照」のように指示しないでください。ビルダーが外部ドキュメントを読む必要がない状態にしてください。
- アセットの抽出を省略しないでください。 実際の画像、動画、フォントがなければ、CSS がどれだけ完璧でもクローンは本物らしく見えません。
- ビルダーエージェントに範囲を広げすぎないでください。 セクションが複雑で、ビルダーへのプロンプトが長くなってきたら、作業を小さなタスクに分割する必要があるということです。
- 無関係なセクションを 1 つのエージェントにまとめないでください。 CTA セクションとフッターは、デザインの異なる別々のコンポーネントです。両方を 1 つのエージェントに任せて、うまくいくことを期待しないでください。
- レスポンシブ表示の抽出を省略しないでください。 デスクトップ幅でしか確認しないと、クローンはタブレットやモバイルで崩れます。抽出時に 1440、768、390 の幅でテストしてください。
- スムーズスクロールライブラリを見落とさないでください。 Lenis(
.lenisクラス)、Locomotive Scroll などが使われていないか確認してください。ブラウザー標準のスクロールは明らかに操作感が異なり、ユーザーはすぐに気づきます。 - 仕様ファイルなしでビルダーを割り当てないでください。 仕様ファイルがあることで、網羅的な抽出が強制され、監査可能な成果物が作成されます。省略すると、ビルダーに渡せる情報は、記憶を頼りにプロンプトへ書ける範囲だけになります。
完了
完了したら、次の内容を報告してください。
- 作成したセクションの合計数
- 作成したコンポーネントの合計数
- 作成した仕様ファイルの合計数(コンポーネント数と一致するはずです)
- ダウンロードしたアセットの合計数(画像、動画、SVG、フォント)
- ビルドの状態(
npm run buildの結果) - ビジュアル QA の結果(残っている不一致があれば記載)
- 既知の不足点や制限事項