ai-vibe-slides について
ブラウザーでの発表や印刷・PDF出力に対応する、単一の HTML または React ファイル形式のスライドデッキを作るスキルです。構成案、デザイン方針、レイアウト、操作方法、レスポンシブ対応と印刷用スタイルを扱います。
主な機能
- 01単一ファイルのHTMLまたはReactデッキ生成
- 02対象者に合わせた構成案の作成
- 03一貫したビジュアル方針の選択
- 04キーボードとクリックでの操作
- 05印刷・PDF向けスタイルの準備
活用シーン
- 01短いテーマからプレゼンを作成
- 02ピッチ資料や学術発表の作成
- 03スライド内容と見た目の修正
- 04ブラウザーでの発表やファイル出力
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ unclecatvn/ agent-skills --skill ai-vibe-slidesインストール後、Claude Code で/ai-vibe-slidesを入力して読み込まれたか確認します。
詳細
AI Vibe Slides — 美しいHTMLスライドデッキ、そのまま発表可能
目標
次のことができる、完成したスライドデッキを含む単一のHTMLまたはReactアーティファクトファイルを作成します。
- ブラウザーで直接、全画面表示する
- 矢印キー、スペースキー、クリックで移動する
- プロフェッショナルで洗練され、スタイルに一貫性がある
- 必要に応じて印刷またはPDFにエクスポートする
banana-slidesに着想を得た、アイデア → アウトライン → 完成スライドの3ステップのパイプラインですが、出力はフルスタックアプリケーションではなく、自己完結型のHTMLファイルです。
スライド作成パイプライン
ステップ1:リクエストを理解する → アウトラインを作成する
ユーザーがリクエストを提示したら、まず頭の中でアウトラインを作成します(ユーザーから求められない限り、表示する必要はありません)。
- メインテーマと対象読者(学生、ビジネスパーソン、技術系の講演参加者など)を特定します
- 論理的なセクションに分割します。
- スライド1:表紙(タイトル+サブタイトル+作者)
- スライド2〜3:導入/背景
- 中盤のスライド:中心となる内容(1枚につき重要なアイデアは1つ)
- 最終スライド:まとめ/行動喚起/謝辞
- 各スライドには、タイトル、2〜5個の箇条書きまたはビジュアルコンテンツ、レイアウトタイプを含めます
ユーザーの入力が短い一文(例:「医療におけるAIについてのスライドを作成」)だけの場合は、論理的な構成で8〜12枚のスライドに自動的に展開します。
ステップ2:デザインの方向性を選ぶ
コンテキストに基づいて、明確なデザインの方向性を1つ決めます。
| コンテキスト | 推奨スタイル |
|---|---|
| スタートアップのピッチデッキ | 大胆なダークテーマ、グラデーションのアクセント、力強いサンセリフ体 |
| 学術/教育 | すっきりした明るいデザイン、図解を多用し、読みやすいフォント |
| 技術系の講演/カンファレンス | モダンなダークテーマ、コード風のタイポグラフィ、ネオンのアクセント |
| 企業/レポート | ミニマルでプロフェッショナルなデザイン、ネイビー/ホワイト、セリフ体の見出し |
| クリエイティブ/マーケティング | カラフルで非対称なレイアウト、大胆なタイポグラフィ |
| 子ども/幼児教育 | パステルカラー、丸みのある角、遊び心のあるアイコン、大きな文字 |
一般的なルール:
- メインカラーを2〜3色選び、デッキ全体で一貫して使用します
- 見出し用フォントを1つ+本文用フォントを1つ(Google Fontsを使用)
- テキストは最小限にし、余白を十分に取ります — 1枚あたり最大5〜6行
- 明確な視覚的階層:大きなタイトル → 中くらいのコンテンツ → 小さな注記
ステップ3:HTML/Reactのスライドデッキを生成する
すべてを含む単一ファイル(.htmlまたは.jsx)を作成します。
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
href="https://fonts.googleapis.com/css2?family={Font1}&family={Font2}&display=swap"
rel="stylesheet"
/>
<style>
/* === RESET + BASE === */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* === SLIDE CONTAINER === */
.slide-deck {
width: 100vw;
height: 100vh;
overflow: hidden;
position: relative;
}
.slide {
width: 100%;
height: 100%;
display: none;
flex-direction: column;
justify-content: center;
padding: 60px 80px;
position: absolute;
top: 0;
left: 0;
}
.slide.active {
display: flex;
}
/* === TYPOGRAPHY === */
h1 {
font-family: "{Font1}", sans-serif;
font-size: 3.2rem;
margin-bottom: 1rem;
}
h2 {
font-family: "{Font1}", sans-serif;
font-size: 2.4rem;
margin-bottom: 1.5rem;
}
p,
li {
font-family: "{Font2}", sans-serif;
font-size: 1.4rem;
line-height: 1.8;
}
/* === THEME COLORS === */
:root {
--bg-primary: #0f172a;
--bg-slide: #1e293b;
--text-primary: #f8fafc;
--text-secondary: #94a3b8;
--accent: #3b82f6;
--accent-2: #8b5cf6;
}
/* === NAVIGATION UI === */
.nav-hint {
position: fixed;
bottom: 20px;
right: 30px;
font-size: 0.8rem;
color: var(--text-secondary);
opacity: 0.5;
}
.slide-counter {
position: fixed;
bottom: 20px;
left: 30px;
font-size: 0.8rem;
color: var(--text-secondary);
}
/* === TRANSITIONS === */
.slide {
animation: fadeIn 0.4s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* === LAYOUT VARIANTS === */
.slide.cover {
justify-content: center;
align-items: center;
text-align: center;
}
.slide.two-column {
flex-direction: row;
gap: 60px;
align-items: center;
}
.slide.two-column .col {
flex: 1;
}
.slide.centered {
align-items: center;
text-align: center;
}
/* === VISUAL ELEMENTS === */
.card {
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
padding: 24px;
margin: 8px 0;
}
.badge {
display: inline-block;
background: var(--accent);
color: white;
padding: 4px 14px;
border-radius: 20px;
font-size: 0.85rem;
}
.divider {
width: 60px;
height: 4px;
background: var(--accent);
border-radius: 2px;
margin: 16px 0;
}
.icon-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
}
/* === PRINT / PDF EXPORT === */
@media print {
.slide {
page-break-after: always;
display: flex !important;
position: relative;
}
.nav-hint,
.slide-counter {
display: none;
}
}
</style>
</head>
<body>
<div class="slide-deck" id="deck">
<div
class="slide cover active"
style="background: linear-gradient(135deg, var(--bg-primary), #1a1a2e);"
>
<div class="badge">Topic</div>
<h1 style="font-size: 3.8rem; margin-top: 20px;">Main Title</h1>
<p
style="color: var(--text-secondary); font-size: 1.3rem; margin-top: 12px;"
>
Short subtitle description
</p>
<div class="divider" style="margin: 20px auto;"></div>
<p style="color: var(--text-secondary); font-size: 1rem;">
Author — Date
</p>
</div>
<div class="slide">
<h2>Slide Title</h2>
<div class="divider"></div>
<ul>
<li>Key point 1</li>
<li>Key point 2</li>
<li>Key point 3</li>
</ul>
</div>
</div>
<div class="slide-counter">
<span id="current">1</span> / <span id="total"></span>
</div>
<div class="nav-hint">← → or click to navigate</div>
<script>
const slides = document.querySelectorAll(".slide");
let currentSlide = 0;
document.getElementById("total").textContent = slides.length;
function showSlide(n) {
slides[currentSlide].classList.remove("active");
currentSlide = (n + slides.length) % slides.length;
slides[currentSlide].classList.add("active");
document.getElementById("current").textContent = currentSlide + 1;
}
document.addEventListener("keydown", (e) => {
if (e.key === "ArrowRight" || e.key === " ")
showSlide(currentSlide + 1);
if (e.key === "ArrowLeft") showSlide(currentSlide - 1);
if (e.key === "f") document.documentElement.requestFullscreen?.();
if (e.key === "Escape") document.exitFullscreen?.();
});
document.querySelector(".slide-deck").addEventListener("click", (e) => {
const x = e.clientX / window.innerWidth;
x > 0.5 ? showSlide(currentSlide + 1) : showSlide(currentSlide - 1);
});
</script>
</body>
</html>
スライドのレイアウトタイプ
各スライドでは、内容に最も適したレイアウトを使用します。
1. 表紙スライド
- 中央揃えの特大フォント、グラデーション背景
- トピックバッジ+メインタイトル+サブタイトル+作者
2. セクション区切り
- セクションタイトル+番号のみ、アクセントカラーの背景
- プレゼンテーションの主要なセクションを分けるために使用
3. コンテンツ+箇条書き
- 左揃えのタイトル+重要なポイントのリスト
- 通常のドットの代わりに、各箇条書きの先頭にアイコン/絵文字を使用
4. 2カラム
.two-columnレイアウト:左側にテキスト、右側にビジュアル/リスト/カード- 比較、ビフォーアフター、テキスト+イラストに最適
5. カードグリッド
- 2〜3列のグリッド。各カードにはアイコン+タイトル+短い説明を含めます
- 機能、メリット、チームメンバーの紹介に最適
6. 大きな数字/統計
- 中央に大きな数字(font-size: 5rem以上)+その下に小さなラベル
- データポイント、KPI、インパクトを示す数値に最適
7. 引用/ハイライト
- 装飾的な引用符を添えた、大きな中央揃えのテキスト
- 背景は別の色(淡いアクセントカラー)
8. タイムライン/手順
- 各ステップをつなぐドットを配置した、横方向または縦方向のフレックスボックス
- プロセス、ロードマップ、歴史の説明に最適
9. 謝辞/CTA
- 中央揃えのシンプルなデザイン。連絡先情報または行動喚起を記載
必須のデザインルール
- 16:9 のアスペクト比:常に
width: 100vw; height: 100vhを使用し、各スライドが画面全体に表示されるようにします - テキストは最小限に:1 枚のスライドにつき最大 6 行です。内容が長い場合は、複数のスライドに分割します
- 大きなフォントサイズ:見出しは 2.4rem 以上、本文は 1.3rem 以上にします。プロジェクターでも読みやすいサイズにしてください
- 高いコントラスト:テキストが背景に対してはっきり読めるようにします。見た目を確認してください
- 一貫性:デッキ全体で、フォント、カラーパレット、余白を統一します
- プレースホルダー画像を使わない:
<img src="placeholder">は使用しないでください。代わりに CSS の図形、グラデーション、アイコン(絵文字または React 用 Lucide)、インライン SVG を使用します - 控えめなアニメーション:スライド切り替え時の fadeIn のみを使用します。注意をそらす複雑なアニメーションは使いません
- 全画面表示に対応:あらゆる画面サイズで適切に動作するようにします
- 印刷対応:各スライドが印刷時に 1 ページになるよう、
@media printルールを含めます
HTML の代わりに React(.jsx)を使用する場合
React の成果物を作成する場合は、次のパターンを使用します。
import { useState, useEffect, useCallback } from "react";
const slides = [
{ type: "cover", title: "...", subtitle: "..." },
{ type: "content", title: "...", points: ["...", "..."] },
{ type: "twoColumn", title: "...", left: "...", right: "..." },
// ...
];
export default function SlideDeck() {
const [current, setCurrent] = useState(0);
const next = useCallback(
() => setCurrent((c) => (c + 1) % slides.length),
[],
);
const prev = useCallback(
() => setCurrent((c) => (c - 1 + slides.length) % slides.length),
[],
);
useEffect(() => {
const handleKey = (e) => {
if (e.key === "ArrowRight" || e.key === " ") next();
if (e.key === "ArrowLeft") prev();
if (e.key === "f") document.documentElement.requestFullscreen?.();
};
window.addEventListener("keydown", handleKey);
return () => window.removeEventListener("keydown", handleKey);
}, [next, prev]);
const renderSlide = (slide) => {
switch (slide.type) {
case "cover":
return /* cover layout */;
case "content":
return /* content layout */;
case "twoColumn":
return /* two-column layout */;
// ...
}
};
return (
<div
className="w-screen h-screen overflow-hidden relative"
onClick={(e) => (e.clientX > window.innerWidth / 2 ? next() : prev())}
style={{ fontFamily: "'Outfit', sans-serif" }}
>
{renderSlide(slides[current])}
<div className="fixed bottom-5 left-8 text-sm opacity-40">
{current + 1} / {slides.length}
</div>
</div>
);
}
React を使う利点:Tailwind CSS ユーティリティ、Lucide アイコン、より複雑なロジック、グラフ用の recharts。
納品前チェックリスト
- スライドの枚数が正しい(表紙+内容+締め)
- 矢印キー ← → が機能し、クリックで移動できる
- カウンターに正しい「X / N」が表示される
- F キーで全画面表示にできる
- すべてのテキストが十分なコントラストで読みやすい
- 画像の破損やプレースホルダーがない
- Google Fonts が正しく読み込まれる(または適切な代替フォントが使われる)
- 印刷/PDF に正しく出力される(
@media print) - デッキ全体でスタイルが統一されている
- 各スライドの要点は 1 つで、テキストを詰め込みすぎていない
自然言語による編集
初回作成後、ユーザーは変更を依頼できます。
- 「ライトテーマに切り替えて」→ CSS 変数を更新します
- 「事例研究についてのスライドを 2 枚追加して」→ 配列にスライドを挿入します
- 「スライド 3 のテキストが多すぎるので、分割して」→ スライド間で内容を再構成します
- 「フォントを Playfair Display に変更して」→ Google Fonts のリンクと CSS を更新します
- 「スライド 5 にグラフを追加して」→ CSS のグラフまたは recharts(React)を使用します
編集のたびに、変更しないスライドはそのまま維持し、ユーザーが依頼した内容だけを更新します。
コメント
Markdown 対応