Communitygithub.com

biLINE: Figma → ランディングページ (HTML/CSS/JS)

Figma MCPを使用して、FigmaデザインからクリーンなHTML/CSS/JSランディングページをブロックごとに作成し、ユーザーの確認を得ながら進めます。ユーザーがFigmaリンク(ファイル全体、デスクトップフレーム、モバイルフレーム)を渡し、HTML/CSS/JSでランディングページを構築/実装するよう依頼した場合に使用します。

CSS/JS) とは?

このスキルは、Figmaデザインを高品質なHTML/CSS/JSランディングページに変換するための包括的なワークフローを提供します。Figma MCP(Model Context Protocol)を利用してデザインデータを取得し、ブロックごとに順次実装していくことで、複雑なレイアウトでも確実に再現できます。主な特徴は、各セクションの実装後にユーザーの確認を求める反復プロセス、BEM命名規則とレスポンシブデザイン(clamp()とメディアクエリ)の適用、画像の最適化(WebP変換、2x解像度)、そしてインラインSVGやcurrentColorを使用したインタラクティブなホバー効果の実装です。また、モーダルウィンドウ、フォームバリデーション、アニメーション、スライダーなどの高度な機能も必要に応じて追加できます。このスキルは、Claude CodeやCodexなどのAIエージェントと連携して動作し、Figma MCPが接続されていることが前提です。

対応~Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/biolineX/figma-landing/tree/HEAD

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

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

ドキュメント

Figma → HTML/CSS/JSランディングページ

このスキルはFigmaのランディングページデザインを、静的なHTML/CSS/JSに変換します。 作業はブロックごとに進められ、各ブロックの後にエージェントが停止し、ユーザーの確認を待ちます。

コーディングルール(構造、BEM、単位、画像、ホバー効果など)は、このスキルの templates/AGENTS.md に定義されています。ステップ3でこのファイルがプロジェクトルートにコピーされ、以降は常に適用されます。

要件

  • Figma MCP が接続されていること(get_metadata、get_design_context、get_screenshot、可能であれば get_variable_defs)。接続されていない場合は、ユーザーにその旨を伝えて停止します。
  • ユーザーが https://www.figma.com/design/:fileKey/:fileName?node-id=1-2 形式のリンクを提供していること。
  • ローカルサーバー、スクリーンショット、WebP変換にはNode.jsが必要です。初回実行時の npx コマンドはパッケージをネットワークからダウンロードするため、Codexが許可を求める場合がありますが、これは正常な動作です。

作業手順

以下のステップを順に、飛ばさずに実行します。

ステップ 1. リンクを解析する

  • fileKey: /design/ の後の部分。リンクに /branch/:branchKey/ が含まれる場合は branchKey を使用します。
  • nodeId: node-id の値。ハイフンをコロンに置き換えます(1-2 → 1:2)。
  • リンクは、ドキュメント全体、ページ、デスクトップフレーム、またはモバイルフレームを指す場合があります。タイプはステップ2で特定します。

ステップ 2. マップの作成

  1. リンクのノードに対して get_metadata を呼び出します(ドキュメント全体の場合は node-id なし、またはルートページを指定)。
  2. ランディングページのバージョンフレーム(デスクトップ、モバイル、時にはタブレット)を見つけます。幅はデザインから特定し、標準値を当てはめないでください。また、モーダルウィンドウ(ポップアップ)やモバイルメニューのフレームがページ内にあれば、それらも個別に見つけます。
  3. 各フレーム内で、トップレベルのセクション(ヘッダー、ヒーロー、メリット、お客様の声、フッターなど)を抽出します。
  4. バージョン間でセクションを対応付けます:「デスクトップセクション ↔ モバイルセクション」(レイヤー名、順序、内容に基づく)。
  5. ユーザーにマップを表示し、確認を待ちます:
幅: デスクトップ 1440, モバイル 375
1. header      — 12:30 ↔ 40:2
2. hero        — 12:45 ↔ 40:18
3. advantages  — 13:10 ↔ 41:5
...
モーダルウィンドウ/メニュー:
- mobile-menu  — 45:12
- popup-order  — 46:01

モバイルバージョンがない場合は、その旨を伝え、どうするかユーザーに質問します。

ステップ 3. プロジェクトの骨組みとベースUI

  1. プロジェクトルートに AGENTS.md がない場合、スキルフォルダから templates/AGENTS.md をコピーします。その中の「このランディングページ」セクション(幅、コンテナ、フォント)をステップ2のデータに基づいて記入します。ブレークポイントはデフォルトのままにします。このレイアウトのコーディングが他の幅で崩れる場合にのみ変更し、その新しい値を記録します。
  2. 構造を作成します: index.html、style.css、script.js、assets/icons/
  3. index.html: <!doctype html>、lang="ja"、charset、viewport、ランディングページの内容に応じた <title> と <meta name="description">。ファビコンは追加しません。script.js は defer で読み込みます。
  4. フォント: get_design_context/get_variable_defs から取得し、必要なウェイトのみをGoogle Fontsから display=swap で読み込みます。フォントがGoogle Fontsにない場合は、ユーザーにファイルを依頼し、@font-face で assets/fonts/ から読み込みます。
  5. style.css: リセット(AGENTS.md 参照)、次に :root に色、フォント、余白、コンテナ幅の変数を定義します。値は get_variable_defs から取得します(デザインに変数がある場合)。それ以外の場合は、デザインから収集して丸めます。
  6. ベースコンポーネント: マクロで共通する要素(ボタン、セクションタイトル、入力フィールド)を再利用可能なクラス(.btn、.section-title、.input、.container)として抽出します。デザインに(hover、focus、active の)状態を持つUIキットがない場合、1回だけ、プロジェクト全体の標準的なボタンとリンクのホバールールをユーザーに質問します。回答を AGENTS.md の「このランディングページ」セクションの「UI状態」行に記録します。
  7. ツール(1回限り):
    • バックグラウンドでプロジェクトルートからローカルサーバーを起動します: npx -y serve -l 3000(代替: python3 -m http.server 3000)。すべてのスクリーンショットは http://localhost:3000 から取得し、file:// からは取得しません。
    • スクリーンショットの撮影方法を確認します: Playwright MCP が接続されていればそれを使用し、そうでなければ scripts/shot.cjs スクリプト(「自己チェック」参照)を使用します。
    • 画像コンバーターを確認し(「画像」参照)、結果を記憶します。
  8. 骨組みができたことをユーザーに伝え、最初のブロックに進みます。

ステップ 4. ブロックごとの実装

マップの各セクションについて、上から下へ厳密に順番に(フォームを含むセクションも含む):

  1. データ. デスクトップセクションとそのモバイルペアに対して get_design_context と get_screenshot を呼び出します。
    • 応答が切り詰められていたり大きすぎる場合は、セクションに対して get_metadata を呼び出し、子ノードを個別に取得します。
    • 応答内のコード(通常はReact + Tailwind)は、サイズ、色、構造の参考としてのみ使用します。スタイルをコピーしないでください。
  2. 画像. ブロックのアセットをダウンロードして処理します(「画像」参照)。
  3. コーディング. HTMLブロックを index.html に、スタイルを style.css に(コメント /* ===== hero ===== */ で区切った個別セクションとして)、JS(必要な場合)を script.js に追加します。ステップ3.6のベースクラスを使用し、ボタンやタイトルのコードを重複させないでください。最初にデスクトップ、次に clamp() とメディアクエリを使用してモバイルまでレスポンシブにします。
    • モバイル幅の header には、バーガーメニューをすぐに実装します(マップのフレームに基づくか、ユーザーに確認)。
    • ブロックにフォームがある場合、基本的なブラウザバリデーション属性(required、type="email"、type="tel"、pattern)を使用して実装しますが、JS送信ロジックは追加しません。
  4. 自己チェック. 現在のセクションのみを、デスクトップ、モバイル、および中間幅(1024、768)でスクリーンショットを撮影します。Figmaのスクリーンショットと比較します: 余白、サイズ、フォント、色、改行。問題を見つけたら修正し、再度スクリーンショットを撮影します。
    • Playwright MCP がある場合: 各幅でセクション要素のスクリーンショットを撮影します。
    • MCPがない場合: スキルフォルダのスクリプトを使用します:
      # 1回限り
      mkdir -p .screens && cp <スキルフォルダ>/scripts/shot.cjs .screens/
      npm i playwright --prefix .screens && npx -y playwright install chromium
      # 各ブロック後
      node .screens/shot.cjs http://localhost:3000 .hero 1440,1024,768,375
      
      スクリプトは .screens/<セクション>-<幅>.png を保存し、ページが画面幅を超えて表示される場合は ⚠ 水平スクロール を出力します。この警告が出た場合は、原因を修正します(body に overflow: hidden を設定して隠さない)。
    • セクションのスクリーンショットはブロック確認後に削除します。スクリプト自体と .screens/ 内の node_modules はステップ6で削除します。
  5. 報告と停止. ユーザーに簡潔に報告します: 何をしたか、デザインからどのような逸脱があったかとその理由、ブロックのユニークなインタラクティブ要素(カードの非標準ホバー、スライダーパラメータ)について確認が必要な点。確認を待ちます。 ユーザーの修正を同じブロックに適用し、再度確認を待ちます。
  6. 「OK」の後でのみ、次のブロックに進みます。

ステップ 5. モーダルウィンドウとフォームロジック

すべてのメインセクションのコーディング後:

  1. ステップ2で見つかった隠しモーダルウィンドウ(ポップアップ)を実装し、開閉トリガー(ボタン、Esc、オーバーレイクリック)を接続します。動作は AGENTS.md の「JavaScript」セクションに従います。
  2. 各ウィンドウを個別のブロックとして扱います: 開いた状態でのスクリーンショットによる自己チェック、報告、確認待ち。
  3. ページ上のすべてのフォームが正しく動作することを確認します。データ送信(fetch/AJAX)は、ユーザーが自ら要求し、エンドポイントまたは仕様を提供するまで実装しません。

ステップ 6. 最終処理

最終ステップの確認後、全幅でページ全体をチェックし、一時ファイルとフォルダ(assets/_raw/、.screens/ 全体)を削除し、バックグラウンドのローカルサーバーを停止し、未使用のスタイルと画像を削除します。簡潔なサマリーを記述します。

画像

  1. ブロックのアセットはFigma MCPの応答から取得します(get_design_context 内の画像リンク)。localhost アドレスが返された場合は、そのままダウンロードします。プレースホルダーやサードパーティのアイコンセットは使用しません。
  2. 一時フォルダ assets/_raw/<ブロック>/ にダウンロードします。ラスター画像は、デザイン上のサイズの2倍(2x)の大きさでダウンロードします。
  3. レスポンシブ画像: モバイルバージョンでトリミングされた(異なるアスペクト比)または意味的に異なる画像が使用されている場合、両方のバージョン(hero-bg-desktop.webp と hero-bg-mobile.webp)をダウンロードし、<picture> で読み込みます。
  4. 分類:
    • インタラクティブ要素(ボタン、リンク)内の小さなアイコンで、ホバー時に色が変わるもの(fill/stroke) → HTMLにインライン <svg fill="currentColor"> として(またはCSS mask-image で)。
    • 静的なアイコン、ロゴ、単純なグラフィック → assets/icons/ にSVGとして、<img> で読み込み(大きなグラフィックの場合はブロックフォルダ)。アイコンがラスターで提供された場合は、ユーザーに伝えます。
    • 写真や複雑な画像 → assets/<ブロック>/ にWebPとして。
  5. WebP変換、品質80。試行順序:
    1. npx -y sharp-cli -i in.png -o out.webp -f webp -q 80(Node.jsが必要)
    2. cwebp -q 80 in.png -o out.webp
    3. どちらもない場合 → 元の形式を維持し、1回だけ、作業を止めずにユーザーに(Node.jsまたは cwebp を)インストールするよう伝えます。
  6. WebPが元のファイルよりも大きい場合 → 元のファイルを維持します。
  7. ファイル名: ラテン文字、小文字、ハイフン区切り、意味のある名前(hero-photo.webp、arrow-right.svg)。
  8. ブロック確認後、assets/_raw/<ブロック>/ を削除します。

ホバー、アニメーション、スライダー

  • ホバー: 基本ボタンとリンクについては、AGENTS.md の「UI状態」行のルールに従います。ブロック内にユニークなインタラクティブカード/要素があり、デザインに状態がない場合、勝手に作成せず、ブロックの報告でユーザーに質問します。
  • スクロールアニメーションとカスタムアニメーション: ユーザーが自ら要求した場合のみ。まず、何を起こしたいのかを明確にします。シンプルなもの(スクロール時の出現)は IntersectionObserver。複雑なもの(ホイール連動、スティッキーセクション、パララックス)はCDN経由のGSAP、ユーザーの同意後。常に prefers-reduced-motion を考慮します。
  • スライダー: シンプルなもの(矢印、ドット、スワイプ)は、CSS scroll-snap と少量のJSで自作。複雑なもの(無限ループ、自動再生、エフェクト、連動スライダー)はCDN経由のSwiper。

よくある問題

  • Figmaの応答が切り詰められる → セクションに対して get_metadata、その後子ノードに対して get_design_context。
  • モバイルセクションのペアやモバイルメニューフレームが見つからない → ユーザーに質問し、勝手に作成しない。
  • フォントの幅がデザインと合わない → ウェイトと letter-spacing を確認し、フォントサイズを調整しない。
  • 画像がダウンロードできない → Figma MCPが実行されているか確認。リンクは変更せずに使用。
  • スクリーンショットでフォントやアイコンが崩れる → サーバーが localhost:3000 で実行されており、file:// ではなくそのサーバーからスクリーンショットを撮影していることを確認。
  • スクリプトが「水平スクロール」と出力する → 画面幅より広い要素(固定幅、大きな gap、端の装飾)を見つけて修正。装飾要素が端にある場合は、そのセクションに overflow-x: clip を設定。
  • アクセシビリティや技術的制限によるデザインからの逸脱 → 許容されますが、ブロックの報告でその旨を伝える。

関連スキル