mcpField
F
frontend-slides

frontend-slides

github.com/gooseworks-aiドキュメント1.3k53 回インストール4 日前に更新
リポジトリ

frontend-slides について

このスキルは非推奨で、デザイナー以外の人がブラウザーで動くアニメーション付きHTMLプレゼンテーションを作成するためのものです。スタイル選びを支援し、各スライドが画面内に収まる単体のデッキを生成します。

主な機能

  1. 01CSSとJavaScriptを含む単一HTMLファイル
  2. 02ビジュアルプレビューによるスタイル選択
  3. 03プリセットを使ったスライドデザイン
  4. 04スライド内スクロールのない画面フィット
  5. 05PowerPoint変換とHTMLプレゼンテーションの改善

活用シーン

  1. 01ブラウザーで表示するピッチデッキの作成
  2. 02ラフなメモからプレゼン資料を構成
  3. 03PowerPointファイルをHTMLスライドに変換
  4. 04既存のHTMLプレゼンテーションを改善

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/gooseworks-ai/goose-skills --skill frontend-slides

インストール後、Claude Code で/frontend-slidesを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

README.md
skill.meta.json
STYLE_PRESETS.md

詳細

非推奨: このスキルは goose-graphics に置き換えられました。skills/composites/goose-graphics/ をご覧ください(npx goose-skills install goose-graphics でインストールできます)。スライド形式は新しいスキルに含まれる7つの形式の1つで、36種類のスタイルプリセットに加え、画像の取得とPNGエクスポートに対応しています。このスキルは、削除まで1リリースサイクルの間、引き続き提供されます。

フロントエンドスライドスキル

ブラウザー上で完全に動作する、依存関係ゼロでアニメーション豊富なHTMLプレゼンテーションを作成します。このスキルでは、ビジュアルを見て選ぶ(「言葉で説明するより、実際に見せる」)ことで、デザインの専門家でない人が好みのスタイルを見つけ、その後、プロダクション品質のスライドデッキを生成できます。

基本理念

  1. 依存関係ゼロ — CSSとJSをインラインで記述した単一のHTMLファイルです。npmもビルドツールも必要ありません。
  2. 言葉で説明するより、実際に見せる — 人は実際に見るまで、自分が何を求めているのか分かりません。抽象的な選択肢ではなく、ビジュアルプレビューを生成します。
  3. 独自性のあるデザイン — ありきたりな「AIが生成したような」見た目を避けます。どのプレゼンテーションも、オーダーメイドのように仕上げます。
  4. プロダクション品質 — コードには適切なコメントを付け、アクセシビリティとパフォーマンスに配慮します。
  5. ビューポートへの収まり(重要) — すべてのスライドをビューポート内に正確に収める必要があります。スライド内のスクロールは一切禁止です。これは譲れない要件です。

重要:ビューポートへの収まりに関する要件

このセクションは、すべてのプレゼンテーションで必須です。どの画面サイズでも、すべてのスライドをスクロールせずに完全に表示できるようにしてください。

黄金律
Each slide = exactly one viewport height (100vh/100dvh)
Content overflows? → Split into multiple slides or reduce content
Never scroll within a slide.
コンテンツ密度の上限

ビューポート内に収めるため、スライドごとに以下の上限を適用してください。

スライドの種類コンテンツの上限
タイトルスライド見出し1つ+サブタイトル1つ+任意のキャッチコピー
コンテンツスライド見出し1つ+箇条書き4~6項目、または見出し1つ+段落2つ
機能グリッド見出し1つ+カード最大6枚(2×3または3×2のグリッド)
コードスライド見出し1つ+コード最大8~10行
引用スライド引用1つ(最大3行)+出典
画像スライド見出し1つ+画像1枚(高さ最大60vh)

コンテンツがこの上限を超える場合 → 複数のスライドに分割します

必須のCSS構成

すべてのプレゼンテーションに、ビューポート内に収めるための以下の基本CSSを含めてください。

/* ===========================================
   VIEWPORT FITTING: MANDATORY BASE STYLES
   These styles MUST be included in every presentation.
   They ensure slides fit exactly in the viewport.
   =========================================== */

/* 1. Lock html/body to viewport */
html, body {
    height: 100%;
    overflow-x: hidden;
}

html {
    scroll-snap-type: y mandatory;
    scroll-behavior: smooth;
}

/* 2. Each slide = exact viewport height */
.slide {
    width: 100vw;
    height: 100vh;
    height: 100dvh; /* Dynamic viewport height for mobile browsers */
    overflow: hidden; /* CRITICAL: Prevent ANY overflow */
    scroll-snap-align: start;
    display: flex;
    flex-direction: column;
    position: relative;
}

/* 3. Content container with flex for centering */
.slide-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    max-height: 100%;
    overflow: hidden; /* Double-protection against overflow */
    padding: var(--slide-padding);
}

/* 4. ALL typography uses clamp() for responsive scaling */
:root {
    /* Titles scale from mobile to desktop */
    --title-size: clamp(1.5rem, 5vw, 4rem);
    --h2-size: clamp(1.25rem, 3.5vw, 2.5rem);
    --h3-size: clamp(1rem, 2.5vw, 1.75rem);

    /* Body text */
    --body-size: clamp(0.75rem, 1.5vw, 1.125rem);
    --small-size: clamp(0.65rem, 1vw, 0.875rem);

    /* Spacing scales with viewport */
    --slide-padding: clamp(1rem, 4vw, 4rem);
    --content-gap: clamp(0.5rem, 2vw, 2rem);
    --element-gap: clamp(0.25rem, 1vw, 1rem);
}

/* 5. Cards/containers use viewport-relative max sizes */
.card, .container, .content-box {
    max-width: min(90vw, 1000px);
    max-height: min(80vh, 700px);
}

/* 6. Lists auto-scale with viewport */
.feature-list, .bullet-list {
    gap: clamp(0.4rem, 1vh, 1rem);
}

.feature-list li, .bullet-list li {
    font-size: var(--body-size);
    line-height: 1.4;
}

/* 7. Grids adapt to available space */
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
    gap: clamp(0.5rem, 1.5vw, 1rem);
}

/* 8. Images constrained to viewport */
img, .image-container {
    max-width: 100%;
    max-height: min(50vh, 400px);
    object-fit: contain;
}

/* ===========================================
   RESPONSIVE BREAKPOINTS
   Aggressive scaling for smaller viewports
   =========================================== */

/* Short viewports (< 700px height) */
@media (max-height: 700px) {
    :root {
        --slide-padding: clamp(0.75rem, 3vw, 2rem);
        --content-gap: clamp(0.4rem, 1.5vw, 1rem);
        --title-size: clamp(1.25rem, 4.5vw, 2.5rem);
        --h2-size: clamp(1rem, 3vw, 1.75rem);
    }
}

/* Very short viewports (< 600px height) */
@media (max-height: 600px) {
    :root {
        --slide-padding: clamp(0.5rem, 2.5vw, 1.5rem);
        --content-gap: clamp(0.3rem, 1vw, 0.75rem);
        --title-size: clamp(1.1rem, 4vw, 2rem);
        --body-size: clamp(0.7rem, 1.2vw, 0.95rem);
    }

    /* Hide non-essential elements */
    .nav-dots, .keyboard-hint, .decorative {
        display: none;
    }
}

/* Extremely short (landscape phones, < 500px height) */
@media (max-height: 500px) {
    :root {
        --slide-padding: clamp(0.4rem, 2vw, 1rem);
        --title-size: clamp(1rem, 3.5vw, 1.5rem);
        --h2-size: clamp(0.9rem, 2.5vw, 1.25rem);
        --body-size: clamp(0.65rem, 1vw, 0.85rem);
    }
}

/* Narrow viewports (< 600px width) */
@media (max-width: 600px) {
    :root {
        --title-size: clamp(1.25rem, 7vw, 2.5rem);
    }

    /* Stack grids vertically */
    .grid {
        grid-template-columns: 1fr;
    }
}

/* ===========================================
   REDUCED MOTION
   Respect user preferences
   =========================================== */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.2s !important;
    }

    html {
        scroll-behavior: auto;
    }
}
はみ出し防止チェックリスト

プレゼンテーションを生成する前に、以下を念頭に置いて確認してください。

  1. ✅ すべての .slide に height: 100vh; height: 100dvh; overflow: hidden; がある
  2. ✅ すべてのフォントサイズに clamp(min, preferred, max) を使用している
  3. ✅ すべての余白に clamp() またはビューポート単位を使用している
  4. ✅ コンテンツコンテナに max-height の制約がある
  5. ✅ 画像に max-height: min(50vh, 400px) などを設定している
  6. ✅ グリッドのレスポンシブな列に auto-fit と minmax() を使用している
  7. ✅ 高さ700px、600px、500pxに対応するブレークポイントがある
  8. ✅ コンテンツ要素に固定のピクセル高を指定していない
  9. ✅ 各スライドのコンテンツ量が密度の上限を守っている
コンテンツが収まらない場合

コンテンツが多すぎる場合:

すること:

  • 複数のスライドに分割する
  • 箇条書きの数を減らす(スライドごとに最大5~6項目)
  • テキストを短くする(各項目は1~2行を目安にする)
  • コードスニペットを短くする
  • 「続き」のスライドを作成する

しないこと:

  • 読みやすさを損なうほどフォントサイズを小さくする
  • パディングや余白を完全になくす
  • スクロールを許可する
  • コンテンツを無理に詰め込む
ビューポートへの収まりをテストする

生成後、以下のサイズでテストするようユーザーに勧めてください。

  • デスクトップ:1920×1080、1440×900、1280×720
  • タブレット:1024×768、768×1024(縦向き)
  • モバイル:375×667、414×896
  • 横向きのスマートフォン:667×375、896×414

フェーズ0:モードの判定

まず、ユーザーが何をしたいのかを判断します。

モードA:新しいプレゼンテーション

  • ユーザーはゼロからスライドを作成したい
  • フェーズ1(コンテンツの把握)に進む

モードB:PPTの変換

  • ユーザーは変換対象のPowerPointファイル(.ppt、.pptx)を持っている
  • フェーズ4(PPTの抽出)に進む

モードC:既存のプレゼンテーションの改善

  • ユーザーはHTMLプレゼンテーションを持っており、改善したい
  • 既存のファイルを読み、構成を把握してから改善する

フェーズ1:コンテンツの把握(新しいプレゼンテーション)

デザインを始める前に、コンテンツを把握します。AskUserQuestionを使って質問します。

ステップ 1.1:プレゼンテーションの背景

質問 1:目的

  • 見出し:「目的」
  • 質問:「このプレゼンテーションの目的は何ですか?」
  • 選択肢:
    • 「ピッチデッキ」 — 投資家や顧客にアイデア、製品、または会社を売り込む
    • 「授業/チュートリアル」 — 概念、手順ガイド、教育コンテンツを説明する
    • 「カンファレンストーク」 — イベント、技術講演、基調講演で話す
    • 「社内プレゼンテーション」 — チームの近況報告、戦略会議、会社の近況報告

質問 2:スライド枚数

  • 見出し:「長さ」
  • 質問:「スライドはおよそ何枚ですか?」
  • 選択肢:
    • 「短め(5~10枚)」 — 手短なピッチ、ライトニングトーク
    • 「中程度(10~20枚)」 — 標準的なプレゼンテーション
    • 「長め(20枚以上)」 — 詳細な解説、包括的な講演

質問 3:コンテンツ

  • 見出し:「コンテンツ」
  • 質問:「コンテンツはすでに用意されていますか?それとも構成を考えるサポートが必要ですか?」
  • 選択肢:
    • 「コンテンツはすべて用意できています」 — プレゼンテーションのデザインだけが必要
    • 「大まかなメモがあります」 — スライドにまとめるサポートが必要
    • 「テーマだけ決まっています」 — 全体のアウトラインを作成するサポートが必要

ユーザーにコンテンツがある場合は、テキスト、箇条書き、画像などを共有してもらいます。


フェーズ 2:スタイルの探求(ビジュアルの確認)

重要:このフェーズでは「説明より実物を見せる」ことが大切です。

多くの人は、デザインの好みを言葉で説明できません。「ミニマルなものと大胆なもののどちらがよいですか?」と尋ねる代わりに、ミニプレビューを作成し、見た人の反応を確認します。

プリセットの選び方

ユーザーは2つの方法でスタイルを選べます。

オプション A:ガイド付きの選択(デフォルト)

  • ユーザーが雰囲気に関する質問に回答する
  • スキルが回答をもとにプレビューファイルを 3 つ生成する
  • ユーザーがブラウザーでプレビューを確認し、気に入ったものを選ぶ
  • 特定のスタイルが決まっていないユーザーに最適です

オプション B:直接選択

  • 希望するスタイルがすでに決まっている場合は、名前を指定してプリセットを選べます
  • 例:「Bold Signal スタイルを使って」や「Dark Botanical のようなものがほしい」
  • すぐにフェーズ 3 に進みます

利用可能なプリセット:

プリセット雰囲気おすすめの用途
Bold Signal自信に満ちた、インパクトの強いピッチデッキ、基調講演
Electric Studio洗練された、プロフェッショナルな代理店のプレゼンテーション
Creative Voltageエネルギッシュな、レトロモダンなクリエイティブなピッチ
Dark Botanicalエレガントな、洗練されたプレミアムブランド
Notebook Tabsエディトリアルな、整理されたレポート、レビュー
Pastel Geometry親しみやすい、気軽に接しやすい製品概要
Split Pastel遊び心のある、モダンなクリエイティブエージェンシー
Vintage Editorialウィットに富んだ、個性を感じるパーソナルブランド
Neon Cyber未来的な、テクノロジー感のあるテック系スタートアップ
Terminal Green開発者向けの開発ツール、API
Swiss Modernミニマルな、精密な企業向け、データ
Paper & Ink文学的な、思慮深いストーリーテリング
ステップ 2.0:スタイルの選択方法

まず、スタイルの選び方をユーザーに尋ねます。

質問:スタイルの選択方法

  • 見出し:「スタイル」
  • 質問:「プレゼンテーションのスタイルをどのように選びますか?」
  • 選択肢:
    • 「選択肢を見せてください」— ニーズに合わせてプレビューを 3 つ生成します(ほとんどのユーザーにおすすめ)
    • 「希望するスタイルが決まっています」— プリセットの一覧から直接選べます
    • 「クライアントのブランドを使用する」— クライアントのブランドカラー、フォント、雰囲気を適用します

「選択肢を見せてください」の場合 → ステップ 2.1(ムードの選択)に進みます

「希望するスタイルが決まっています」の場合 → プリセット選択画面を表示します。

質問:プリセットを選択

  • 見出し:「プリセット」
  • 質問:「使用するスタイルを選んでください。」
  • 選択肢:
    • 「Bold Signal」— 暗い背景に鮮やかなカードを配した、自信に満ちた力強いスタイル
    • 「Dark Botanical」— 柔らかな抽象図形をあしらった、エレガントなダークスタイル
    • 「Notebook Tabs」— カラフルなセクションタブを配した、エディトリアルな紙のようなスタイル
    • 「Pastel Geometry」— 装飾的なピルをあしらった、親しみやすいパステルスタイル

(ユーザーがいずれかを選んだら、フェーズ 3 に進みます。さらに選択肢を見たい場合は、追加のプリセットを表示するか、ガイド付きの選択に進みます。)

「クライアントのブランドを使用する」の場合 → クライアントのビジュアルアイデンティティを読み込みます。

  1. このプレゼンテーションの対象となるクライアントを尋ねます(または、文脈から推測します)。
  2. clients/<client-name>/brand/visual-identity.md があるか確認します。
  3. ファイルがある場合:「Slide Preset」セクションを読み込みます。CSS の :root カスタムプロパティをプレゼンテーションのテーマ変数として、タイポグラフィをフォントの組み合わせとして、フォント読み込み用の <link> タグをそのまま使用し、シグネチャー要素を装飾用 CSS のデザイン指針として使用します。
  4. ファイルがない場合: ユーザーに次のように伝えます。「[client] のビジュアルアイデンティティはまだ抽出されていません。今すぐ抽出しますか?クライアントのウェブサイト URL を入力してください。」続いて、visual-brand-extractor スキルを実行してファイルを生成し、そのまま続行します。
  5. クライアントのプリセットを読み込んだ状態でフェーズ 3 に進みます。
ステップ 2.1:ムードの選択(ガイド付きの選択)

質問 1:印象

  • 見出し:「雰囲気」
  • 質問:「スライドを見た人に、どのような印象を持ってほしいですか?」
  • 選択肢:
    • 「感銘/自信」— プロフェッショナルで信頼でき、チームが仕事を熟知している印象
    • 「興奮/活気」— 革新的で大胆、未来を感じさせる印象
    • 「落ち着き/集中」— 明快で思慮深く、内容を追いやすい印象
    • 「ひらめき/感動」— 感情に訴え、ストーリー性があり、記憶に残る印象
  • multiSelect: true(最大 2 つまで選択可能)
ステップ 2.2:スタイルのプレビューを生成

選択されたムードに基づき、一時ディレクトリに単一のタイトルスライドを表示するミニ HTML ファイルとして、異なるスタイルのプレビューを 3 つ生成します。各プレビューには、次の内容を含めます。

  • タイポグラフィ(フォントの選択、見出しと本文の階層)
  • カラーパレット(背景色、アクセントカラー、テキストカラー)
  • アニメーションのスタイル(要素の表示方法)
  • 全体的な美的印象

検討するプレビュースタイル(ムードに応じて 3 つ選択):

ムードスタイルの選択肢
感銘/自信「Bold Signal」、「Electric Studio」、「Dark Botanical」
興奮/活気「Creative Voltage」、「Neon Cyber」、「Split Pastel」
落ち着き/集中「Notebook Tabs」、「Paper & Ink」、「Swiss Modern」
ひらめき/感動「Dark Botanical」、「Vintage Editorial」、「Pastel Geometry」

重要:次のような一般的なパターンは使用しないでください。

  • 白い背景に紫のグラデーション
  • Inter、Roboto、システムフォント
  • 標準的なブルーのプライマリーカラー
  • ありきたりなヒーローレイアウト

代わりに、個性が際立つ選択をしてください。

  • 個性的なフォントの組み合わせ(Clash Display、Satoshi、Cormorant Garamond、DM Sans など)
  • 個性のある統一感の取れたカラーテーマ
  • 雰囲気のある背景(グラデーション、控えめなパターン、奥行き)
  • 印象的なアニメーションの演出
Step 2.3: プレビューを提示する

プレビューを次の場所に作成します:.claude-design/slide-previews/

.claude-design/slide-previews/
├── style-a.html   # First style option
├── style-b.html   # Second style option
├── style-c.html   # Third style option
└── assets/        # Any shared assets

各プレビューファイルは、次の条件を満たす必要があります。

  • 単体で動作する(CSS/JSをインラインで記述)
  • 美しさを伝える単一の「タイトルスライド」である
  • 動きのスタイルを示すアニメーションがある
  • 約50~100行で、プレゼンテーション全体にはしない

ユーザーに提示します。

I've created 3 style previews for you to compare:

**Style A: [Name]** — [1 sentence description]
**Style B: [Name]** — [1 sentence description]
**Style C: [Name]** — [1 sentence description]

Open each file to see them in action:
- .claude-design/slide-previews/style-a.html
- .claude-design/slide-previews/style-b.html
- .claude-design/slide-previews/style-c.html

Take a look and tell me:
1. Which style resonates most?
2. What do you like about it?
3. Anything you'd change?

次に、AskUserQuestion を使用します。

質問:スタイルを選んでください

  • ヘッダー:「スタイル」
  • 質問:「どのスタイルのプレビューがお好みですか?」
  • 選択肢:
    • 「スタイルA:[名前]」 — [簡単な説明]
    • 「スタイルB:[名前]」 — [簡単な説明]
    • 「スタイルC:[名前]」 — [簡単な説明]
    • 「要素を組み合わせる」 — 異なるスタイルの要素を組み合わせます

「要素を組み合わせる」を選んだ場合は、具体的な内容を尋ねます。


Phase 3: プレゼンテーションを生成する

次の内容に基づいて、プレゼンテーション全体を生成します。

  • Phase 1 のコンテンツ
  • Phase 2 のスタイル
ファイル構成

単一のプレゼンテーションの場合:

presentation.html    # Self-contained presentation
assets/              # Images, if any

複数のプレゼンテーションを含むプロジェクトの場合:

[presentation-name].html
[presentation-name]-assets/
HTML アーキテクチャ

すべてのプレゼンテーションで、次の構成に従います。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Presentation Title</title>

    
    <link rel="stylesheet" href="https://api.fontshare.com/v2/css?f[]=...">

    <style>
        /* ===========================================
           CSS CUSTOM PROPERTIES (THEME)
           Easy to modify: change these to change the whole look
           =========================================== */
        :root {
            /* Colors */
            --bg-primary: #0a0f1c;
            --bg-secondary: #111827;
            --text-primary: #ffffff;
            --text-secondary: #9ca3af;
            --accent: #00ffcc;
            --accent-glow: rgba(0, 255, 204, 0.3);

            /* Typography - MUST use clamp() for responsive scaling */
            --font-display: 'Clash Display', sans-serif;
            --font-body: 'Satoshi', sans-serif;
            --title-size: clamp(2rem, 6vw, 5rem);
            --subtitle-size: clamp(0.875rem, 2vw, 1.25rem);
            --body-size: clamp(0.75rem, 1.2vw, 1rem);

            /* Spacing - MUST use clamp() for responsive scaling */
            --slide-padding: clamp(1.5rem, 4vw, 4rem);
            --content-gap: clamp(1rem, 2vw, 2rem);

            /* Animation */
            --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
            --duration-normal: 0.6s;
        }

        /* ===========================================
           BASE STYLES
           =========================================== */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        html {
            scroll-behavior: smooth;
            scroll-snap-type: y mandatory;
            height: 100%;
        }

        body {
            font-family: var(--font-body);
            background: var(--bg-primary);
            color: var(--text-primary);
            overflow-x: hidden;
            height: 100%;
        }

        /* ===========================================
           SLIDE CONTAINER
           CRITICAL: Each slide MUST fit exactly in viewport
           - Use height: 100vh (NOT min-height)
           - Use overflow: hidden to prevent scroll
           - Content must scale with clamp() values
           =========================================== */
        .slide {
            width: 100vw;
            height: 100vh; /* EXACT viewport height - no scrolling */
            height: 100dvh; /* Dynamic viewport height for mobile */
            padding: var(--slide-padding);
            scroll-snap-align: start;
            display: flex;
            flex-direction: column;
            justify-content: center;
            position: relative;
            overflow: hidden; /* Prevent any content overflow */
        }

        /* Content wrapper that prevents overflow */
        .slide-content {
            flex: 1;
            display: flex;
            flex-direction: column;
            justify-content: center;
            max-height: 100%;
            overflow: hidden;
        }

        /* ===========================================
           RESPONSIVE BREAKPOINTS
           Adjust content for different screen sizes
           =========================================== */
        @media (max-height: 600px) {
            :root {
                --slide-padding: clamp(1rem, 3vw, 2rem);
                --content-gap: clamp(0.5rem, 1.5vw, 1rem);
            }
        }

        @media (max-width: 768px) {
            :root {
                --title-size: clamp(1.5rem, 8vw, 3rem);
            }
        }

        @media (max-height: 500px) and (orientation: landscape) {
            /* Extra compact for landscape phones */
            :root {
                --title-size: clamp(1.25rem, 5vw, 2rem);
                --slide-padding: clamp(0.75rem, 2vw, 1.5rem);
            }
        }

        /* ===========================================
           ANIMATIONS
           Trigger via .visible class (added by JS on scroll)
           =========================================== */
        .reveal {
            opacity: 0;
            transform: translateY(30px);
            transition: opacity var(--duration-normal) var(--ease-out-expo),
                        transform var(--duration-normal) var(--ease-out-expo);
        }

        .slide.visible .reveal {
            opacity: 1;
            transform: translateY(0);
        }

        /* Stagger children */
        .reveal:nth-child(1) { transition-delay: 0.1s; }
        .reveal:nth-child(2) { transition-delay: 0.2s; }
        .reveal:nth-child(3) { transition-delay: 0.3s; }
        .reveal:nth-child(4) { transition-delay: 0.4s; }

        /* ... more styles ... */
    </style>
</head>
<body>
    
    <div class="progress-bar"></div>

    
    <nav class="nav-dots">
        
    </nav>

    
    <section class="slide title-slide">
        <h1 class="reveal">Presentation Title</h1>
        <p class="reveal">Subtitle or author</p>
    </section>

    <section class="slide">
        <h2 class="reveal">Slide Title</h2>
        <p class="reveal">Content...</p>
    </section>

    

    <script>
        /* ===========================================
           SLIDE PRESENTATION CONTROLLER
           Handles navigation, animations, and interactions
           =========================================== */

        class SlidePresentation {
            constructor() {
                // ... initialization
            }

            // ... methods
        }

        // Initialize
        new SlidePresentation();
    </script>
</body>
</html>
必須の JavaScript 機能

すべてのプレゼンテーションに、次の機能を含めます。

  1. SlidePresentation クラス — メインコントローラー

    • キーボード操作(矢印キー、スペースキー)
    • タッチ/スワイプ対応
    • マウスホイールによる操作
    • プログレスバーの更新
    • ナビゲーションドット
  2. Intersection Observer — スクロールに応じたアニメーション用

    • スライドがビューポートに入ったときに .visible クラスを追加
    • CSS アニメーションを効率的に実行
  3. 任意の拡張機能(スタイルに応じて)

    • トレイル付きカスタムカーソル
    • パーティクルシステムの背景(canvas)
    • 視差効果
    • ホバー時の3Dチルト
    • マグネティックボタン
    • カウンターアニメーション
コード品質要件

コメント: 各セクションには、次の内容を説明する明確なコメントを付けます。

  • 処理内容
  • 存在する理由
  • 変更方法
/* ===========================================
   CUSTOM CURSOR
   Creates a stylized cursor that follows mouse with a trail effect.
   - Uses lerp (linear interpolation) for smooth movement
   - Grows larger when hovering over interactive elements
   =========================================== */
class CustomCursor {
    constructor() {
        // ...
    }
}

アクセシビリティ:

  • セマンティック HTML(<section>、<nav>、<main>)
  • キーボード操作に対応
  • 必要に応じて ARIA ラベルを使用
  • 動きを抑制する設定に対応
@media (prefers-reduced-motion: reduce) {
    .reveal {
        transition: opacity 0.3s ease;
        transform: none;
    }
}

レスポンシブ対応とビューポートへの適合(重要):

完全な CSS とガイドラインについては、上記の「重要:ビューポートへの適合要件」セクションを参照してください。

簡単な確認項目:

  • すべての .slide に height: 100vh; height: 100dvh; overflow: hidden; を指定する
  • すべての文字サイズと余白に clamp() を使用する
  • コンテンツ量の上限を守る(箇条書きは最大4~6項目、カードは最大6枚など)
  • 高さ700px、600px、500pxのブレークポイントを含める
  • コンテンツが収まらない場合は複数のスライドに分割し、スクロールは使用しない

Phase 4: PPT 変換

PowerPoint ファイルを変換する場合:

Step 4.1: コンテンツを抽出する

python-pptx を使って Python で次の内容を抽出します。

from pptx import Presentation
from pptx.util import Inches, Pt
import json
import os
import base64

def extract_pptx(file_path, output_dir):
    """
    Extract all content from a PowerPoint file.
    Returns a JSON structure with slides, text, and images.
    """
    prs = Presentation(file_path)
    slides_data = []

    # Create assets directory
    assets_dir = os.path.join(output_dir, 'assets')
    os.makedirs(assets_dir, exist_ok=True)

    for slide_num, slide in enumerate(prs.slides):
        slide_data = {
            'number': slide_num + 1,
            'title': '',
            'content': [],
            'images': [],
            'notes': ''
        }

        for shape in slide.shapes:
            # Extract title
            if shape.has_text_frame:
                if shape == slide.shapes.title:
                    slide_data['title'] = shape.text
                else:
                    slide_data['content'].append({
                        'type': 'text',
                        'content': shape.text
                    })

            # Extract images
            if shape.shape_type == 13:  # Picture
                image = shape.image
                image_bytes = image.blob
                image_ext = image.ext
                image_name = f"slide{slide_num + 1}_img{len(slide_data['images']) + 1}.{image_ext}"
                image_path = os.path.join(assets_dir, image_name)

                with open(image_path, 'wb') as f:
                    f.write(image_bytes)

                slide_data['images'].append({
                    'path': f"assets/{image_name}",
                    'width': shape.width,
                    'height': shape.height
                })

        # Extract notes
        if slide.has_notes_slide:
            notes_frame = slide.notes_slide.notes_text_frame
            slide_data['notes'] = notes_frame.text

        slides_data.append(slide_data)

    return slides_data
Step 4.2: コンテンツの構成を確認する

抽出したコンテンツをユーザーに提示します。

I've extracted the following from your PowerPoint:

**Slide 1: [Title]**
- [Content summary]
- Images: [count]

**Slide 2: [Title]**
- [Content summary]
- Images: [count]

...

All images have been saved to the assets folder.

Does this look correct? Should I proceed with style selection?
Step 4.3: スタイルを選択する

抽出したコンテンツを考慮したうえで、Phase 2(スタイルの選定)に進みます。

Step 4.4: HTML を生成する

抽出したコンテンツを選択したスタイルに変換し、次の内容を保持します。

  • すべてのテキストコンテンツ
  • すべての画像(assets フォルダーを参照)
  • スライドの順序
  • スピーカーノート(HTML コメントまたは別ファイルとして保存)

Phase 5: 納品

最終出力

プレゼンテーションが完成したら:

  1. 一時ファイルを整理する

    • .claude-design/slide-previews/ が存在する場合は削除する
  2. プレゼンテーションを開く

    • open [filename].html を使ってブラウザーで開く
  3. 概要を提示する

Your presentation is ready!

📁 File: [filename].html
🎨 Style: [Style Name]
📊 Slides: [count]

**Navigation:**
- Arrow keys (← →) or Space to navigate
- Scroll/swipe also works
- Click the dots on the right to jump to a slide

**To customize:**
- Colors: Look for `:root` CSS variables at the top
- Fonts: Change the Fontshare/Google Fonts link
- Animations: Modify `.reveal` class timings

Would you like me to make any adjustments?

スタイルリファレンス:効果から印象への対応

このガイドを使って、意図する印象に合ったアニメーションを選びます。

ドラマチック/映画的
  • ゆっくりしたフェードイン(1~1.5秒)
  • 大きなスケールのトランジション(0.9 → 1)
  • スポットライト効果を使った暗い背景
  • 視差スクロール
  • 画面いっぱいに表示する画像
テック/未来的
  • ネオンの発光効果(アクセントカラーを使った box-shadow)
  • パーティクルシステム(canvas の背景)
  • グリッドパターン
  • アクセントに等幅フォントを使用
  • グリッチ効果または文字のスクランブル効果
  • シアン、マゼンタ、エレクトリックブルーの配色
遊び心のある/親しみやすい
  • 弾むイージング(バネの物理特性)
  • 角丸(大きな半径)
  • パステルカラーまたは明るい色
  • 浮遊/上下に揺れるアニメーション
  • 手描きまたはイラスト風の要素
プロフェッショナル/企業向け
  • 控えめで素早いアニメーション(200-300ms)
  • クリーンなサンセリフ体
  • ネイビー、スレート、またはチャコールの背景
  • 正確な余白と配置
  • 装飾要素は最小限
  • データビジュアライゼーションを重視
落ち着いた/ミニマル
  • 非常にゆっくりとした控えめな動き
  • 余白を多く取る
  • 彩度を抑えたカラーパレット
  • セリフ体のタイポグラフィ
  • ゆとりのあるパディング
  • コンテンツに集中し、気を散らすものを置かない
エディトリアル/雑誌風
  • 明確なタイポグラフィの階層
  • 引用文とコールアウト
  • 画像とテキストの組み合わせ
  • グリッドからはみ出すレイアウト
  • 見出しはセリフ体、本文はサンセリフ体
  • 黒と白にアクセントカラーを1色

アニメーションパターンのリファレンス

登場アニメーション
/* Fade + Slide Up (most common) */
.reveal {
    opacity: 0;
    transform: translateY(30px);
    transition: opacity 0.6s var(--ease-out-expo),
                transform 0.6s var(--ease-out-expo);
}

.visible .reveal {
    opacity: 1;
    transform: translateY(0);
}

/* Scale In */
.reveal-scale {
    opacity: 0;
    transform: scale(0.9);
    transition: opacity 0.6s, transform 0.6s var(--ease-out-expo);
}

/* Slide from Left */
.reveal-left {
    opacity: 0;
    transform: translateX(-50px);
    transition: opacity 0.6s, transform 0.6s var(--ease-out-expo);
}

/* Blur In */
.reveal-blur {
    opacity: 0;
    filter: blur(10px);
    transition: opacity 0.8s, filter 0.8s var(--ease-out-expo);
}
背景エフェクト
/* Gradient Mesh */
.gradient-bg {
    background:
        radial-gradient(ellipse at 20% 80%, rgba(120, 0, 255, 0.3) 0%, transparent 50%),
        radial-gradient(ellipse at 80% 20%, rgba(0, 255, 200, 0.2) 0%, transparent 50%),
        var(--bg-primary);
}

/* Noise Texture */
.noise-bg {
    background-image: url("data:image/svg+xml,..."); /* Inline SVG noise */
}

/* Grid Pattern */
.grid-bg {
    background-image:
        linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px);
    background-size: 50px 50px;
}
インタラクティブエフェクト
/* 3D Tilt on Hover */
class TiltEffect {
    constructor(element) {
        this.element = element;
        this.element.style.transformStyle = 'preserve-3d';
        this.element.style.perspective = '1000px';
        this.bindEvents();
    }

    bindEvents() {
        this.element.addEventListener('mousemove', (e) => {
            const rect = this.element.getBoundingClientRect();
            const x = (e.clientX - rect.left) / rect.width - 0.5;
            const y = (e.clientY - rect.top) / rect.height - 0.5;

            this.element.style.transform = `
                rotateY(${x * 10}deg)
                rotateX(${-y * 10}deg)
            `;
        });

        this.element.addEventListener('mouseleave', () => {
            this.element.style.transform = 'rotateY(0) rotateX(0)';
        });
    }
}

トラブルシューティング

よくある問題

フォントが読み込まれない場合:

  • Fontshare/Google Fonts の URL を確認してください
  • CSS のフォント名が一致していることを確認してください

アニメーションが開始されない場合:

  • Intersection Observer が動作していることを確認してください
  • .visible クラスが追加されていることを確認してください

スクロールスナップが動作しない場合:

  • html/body に scroll-snap-type が設定されていることを確認してください
  • 各スライドに scroll-snap-align: start が必要です

モバイルでの問題:

  • 768px のブレークポイントで負荷の高いエフェクトを無効にしてください
  • タッチイベントをテストしてください
  • パーティクル数を減らすか、キャンバスを無効にしてください

パフォーマンスの問題:

  • will-change は控えめに使用してください
  • transform と opacity のアニメーションを優先してください
  • スクロール/mousemove のハンドラーをスロットルしてください

関連スキル

  • learn — プレゼンテーション用の FORZARA.md ドキュメントを生成します
  • frontend-design — スライド以外の、より複雑なインタラクティブページ向け
  • design-and-refine:design-lab — コンポーネントのデザインを反復的に調整します

セッションの進行例

  1. ユーザー:「AI スタートアップ向けのピッチデッキを作成したいです」
  2. スキルが目的、長さ、コンテンツについて質問します
  3. ユーザーが箇条書きと重要なメッセージを共有します
  4. スキルが希望する印象(感動と期待)について質問します
  5. スキルがスタイルのプレビューを3種類生成します
  6. ユーザーがスタイル B(ネオン・サイバー)を選び、背景を暗くするよう依頼します
  7. スキルがすべてのスライドを含むプレゼンテーションを生成します
  8. スキルがブラウザーでプレゼンテーションを開きます
  9. ユーザーが特定のスライドの修正を依頼します
  10. 最終版のプレゼンテーションが納品されます

変換セッションの進行例

  1. ユーザー:「slides.pptx をウェブプレゼンテーションに変換してください」
  2. スキルが PPT からコンテンツと画像を抽出します
  3. スキルが抽出したコンテンツをユーザーに確認します
  4. スキルが希望する印象/スタイルについて質問します
  5. スキルがスタイルのプレビューを生成します
  6. ユーザーがスタイルを選びます
  7. スキルがアセットを保持した HTML プレゼンテーションを生成します
  8. 最終版のプレゼンテーションが納品されます

コメント