本記事は サムザップ Advent Calendar 2025 の21日目の記事です。
昨日の記事は @Rom_zai さんの「UniversalRendererDataのEditor拡張してみた」でした。
はじめに
Claude Codeは、Anthropic社が提供するCLI型のAIコーディングアシスタントです。ターミナル上でコードの作成・編集・実行を自然言語で指示できます。
先日、社内でClaude Codeの勉強会を開催しました。1時間半の座学+ハンズオン形式で、約50枚のスライドを用意する必要がありました。
ここで考えたのが「Claude CodeでClaude Codeの勉強会資料を作る」というメタ的なアプローチです。せっかくAIコーディングツールの勉強会なのだから、その制作プロセス自体もAIで効率化してみよう、という試みです。
この記事では、Claude Codeを使ってスライドを効率的に作成するために行った工夫を紹介します。
完成物
最終的に完成したのは、以下のようなスライドです。
スペック:
- 50スライド
- HTML + CSS
- Puppeteerによる自動PDF生成
なぜMarpやReveal.jsではなくピュアHTML+CSSなのか
スライド作成ツールとしてはMarpやReveal.jsが有名ですが、今回はあえてピュアHTML+CSSを選びました。理由は3つあります。
- 完全なレイアウト制御: フレームワークの制約なく、自由にデザインできる
- Claude Codeとの相性の良さ: HTMLはAIが得意な出力形式であり、1発である程度高精度なものが得られる
- 検証目的: Claude CodeがHTML+CSSをどの程度うまく扱えるか試してみたかった
結果として、シンプルなファイル構成で管理しやすく、Claude Codeからの修正指示も通りやすいスライドが完成しました。
制作フローの全体像
今回のスライド制作は、以下の5つのフェーズで進めました。
plot.md → rules.md → tasks.md → 実装 → PDF生成
(台本) (ルール) (タスク分割) (HTML作成)
ポイントは「先に文脈を整えてからClaude Codeに依頼する」というコンテキストエンジニアリング(AIに適切な文脈を与えて出力精度を高める手法)の実践です。
いきなり「スライドを作って」と依頼するのではなく、まず「何を伝えたいか(plot.md)」「どういうデザインルールか(rules.md)」「どの単位で作業するか(tasks.md)」を明文化しておきます。これにより、Claude Codeが一貫性のある出力を生成しやすくなります。
工夫①: plot.md(台本)の作り方
最初に作成したのが plot.md です。これは勉強会の台本で、1時間半の内容を12セクションに分割しています。
各セクションには「時間」「目的」「伝えたいこと」を記載しました。
7. Vibe Codingの流行・限界(5分)
- **定義**
- Vibe Coding = その場のノリ・勢いでAIに投げ、雰囲気で前に進める開発スタイル
- **要点**
- 仕様・制約が曖昧だと、AIはそれっぽいものを作るが、
**業務要件・運用制約・既存設計**を取りこぼしやすい
- 会話が伸びるほど、**目的のドリフト**が起きやすい
このplot.mdがあることで、Claude Codeに「plot.mdのセクション7を読んでスライドを作って」と依頼できる粒度になります。
plot.mdの作成には1時間以上をかけました。ChatGPTと何十回かやり取りしながら、通勤時間や業務の隙間時間を使って並行作業で仕上げました。ここに時間をかけたおかげで、スライド作成時に迷うことがほとんどありませんでした。
工夫②: rules.md(デザインルール)の設計
次に作成したのが rules.md です。スライドの6つのレイアウトパターンを定義しました。
### 5. コード表示スライド
- フォント: `monospace`、24-28px
- 背景: ダークテーマ推奨(#1e1e1e)
- コードは10行以内
### 6. 比較スライド
- 左右対称レイアウト
- 色分け: 悪い例(赤系)、良い例(緑系)
カラースキーム、フォント、余白もCSS変数として統一しました。
### 基本色
| 用途 | 色 | コード |
|------|-----|--------|
| 背景(通常) | 白 | `#ffffff` |
| 本文 | ダークグレー | `#333333` |
| アクセント | ブルー | `#2563eb` |
| 警告 | オレンジ | `#f59e0b` |
rules.mdの作成は約5分で終わりました。ルールを明文化しておくことで、Claude Codeが一貫したデザインを維持できるようになります。
工夫③: tasks.md(タスク分割)の威力
50スライドを一度に作るのは現実的ではありません。そこで、13個の独立したタスクに分割しました。
### Task 5: Vibe Coding(スライド16-20)
@claude-code-study-session/plot.md のセクション7を参照し、
@claude-code-study-session/artifacts/slides.html にスライド16-20を追加してください。
内容:
- スライド16: セクションタイトル「Vibe Codingの流行・限界」
- スライド17: Vibe Codingとは(定義)
- スライド18: Vibe Codingの問題点
- スライド19: Vibe vs コンテキストエンジニアリング(比較)
- スライド20: 悪い投げ方 vs 良い投げ方(コード例)
必要な画像があれば生成し artifacts/images/ に保存してください。
各タスクが「どのスライドを」「どのルールで」作るかを明記しています。
タスク分割の利点:
- コンテキストウィンドウの節約: 1タスクずつ依頼することで、Claude Codeの文脈を効率的に使える
- エラー時の影響範囲を限定: 1タスクが失敗しても、他のタスクには影響しない
- 進捗の可視化: どこまで終わったかが明確
tasks.mdの作成も約5分で終わりました。
工夫④: 画像生成の自動化
スライドには画像が必要です。今回はGemini 3 Pro Image(通称: nano banana pro)を使用し、Claude Skill (+ Pythonプログラム)として定義しました。
$ python3 .claude/skills/image-generator/scripts/generate_image.py \
"A developer sitting at a computer with a carefree, relaxed expression, coding casually with music headphones on. The character is in a flat design illustration style, with a speech bubble showing 'いい感じ!' (looks good!). The background shows messy code snippets floating around. Simple, clean flat design illustration suitable for a presentation slide. White background." \
slide-16-vibe-coding.png --aspect-ratio 16:9
generate_image.py の全体
#!/usr/bin/env python3
"""
Gemini 3 Pro Image (Nano Banana Pro) を使用した画像生成スクリプト
使用方法:
python generate_image.py "プロンプト" [出力ファイル名] [--aspect-ratio RATIO] [--size SIZE]
例:
python generate_image.py "富士山と桜の風景"
python generate_image.py "宇宙飛行士" astronaut.png --aspect-ratio 16:9 --size 2K
"""
import argparse
import os
import sys
from pathlib import Path
from typing import Optional
try:
from google import genai
from google.genai import types
except ImportError:
print("エラー: google-genai パッケージがインストールされていません")
print("以下のコマンドでインストールしてください:")
print(" pip install google-genai")
sys.exit(1)
try:
from dotenv import load_dotenv
except ImportError:
print("エラー: python-dotenv パッケージがインストールされていません")
print("以下のコマンドでインストールしてください:")
print(" pip install python-dotenv")
sys.exit(1)
def find_env_file() -> Optional[Path]:
"""プロジェクトルートの .env ファイルを探す"""
current = Path.cwd()
# カレントディレクトリから親に向かって .env を探す
for parent in [current] + list(current.parents):
env_file = parent / ".env"
if env_file.exists():
return env_file
return None
def load_api_key() -> str:
"""API キーを読み込む"""
env_file = find_env_file()
if env_file:
load_dotenv(env_file)
api_key = os.environ.get("GEMINI_API_KEY")
if not api_key:
print("エラー: GEMINI_API_KEY が設定されていません")
print(".env ファイルに以下の形式で設定してください:")
print(" GEMINI_API_KEY=your-api-key-here")
sys.exit(1)
return api_key
def generate_image(
prompt: str,
output_path: str = "generated_image.png",
aspect_ratio: str = "1:1",
image_size: Optional[str] = None
) -> str:
"""
Gemini 3 Pro Image を使用して画像を生成する
Args:
prompt: 画像生成プロンプト
output_path: 出力ファイルパス
aspect_ratio: アスペクト比 (1:1, 16:9, 9:16, 4:3, 3:4, 21:9)
image_size: 画像サイズ (1K, 2K, 4K) - SDK がサポートしている場合のみ使用
Returns:
生成された画像のファイルパス
"""
api_key = load_api_key()
# クライアントを初期化
client = genai.Client(api_key=api_key)
print(f"画像を生成中: '{prompt}'")
print(f" アスペクト比: {aspect_ratio}")
if image_size:
print(f" サイズ: {image_size}")
try:
# ImageConfig を構築
image_config_params = {"aspect_ratio": aspect_ratio}
# image_size パラメータがサポートされているか確認
if image_size:
try:
# サイズ指定を試みる(サポートされていない場合は無視)
test_config = types.ImageConfig(aspect_ratio=aspect_ratio, image_size=image_size)
image_config_params["image_size"] = image_size
except Exception:
print(f" 注意: image_size パラメータはこのバージョンの SDK でサポートされていません")
image_config = types.ImageConfig(**image_config_params)
# 画像生成リクエスト
response = client.models.generate_content(
model="gemini-3-pro-image-preview",
contents=prompt,
config=types.GenerateContentConfig(
response_modalities=["IMAGE"],
image_config=image_config,
),
)
# レスポンスから画像を取得して保存
image_saved = False
for part in response.candidates[0].content.parts:
if part.inline_data:
# 出力ディレクトリが存在しない場合は作成
output_file = Path(output_path)
output_file.parent.mkdir(parents=True, exist_ok=True)
# 画像データを直接ファイルに書き込む
with open(output_file, "wb") as f:
f.write(part.inline_data.data)
print(f"画像を保存しました: {output_file.absolute()}")
image_saved = True
break
if not image_saved:
# テキストレスポンスがある場合は表示
for part in response.candidates[0].content.parts:
if part.text:
print(f"モデルからのメッセージ: {part.text}")
print("警告: 画像が生成されませんでした")
sys.exit(1)
return str(output_file.absolute())
except Exception as e:
print(f"エラーが発生しました: {e}")
sys.exit(1)
def main():
parser = argparse.ArgumentParser(
description="Gemini 3 Pro Image (Nano Banana Pro) を使用して画像を生成する",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
使用例:
%(prog)s "富士山と桜の風景"
%(prog)s "宇宙飛行士が月面でコーヒーを飲んでいる" astronaut.png
%(prog)s "サイバーパンク風の東京の夜景" tokyo.png --aspect-ratio 16:9 --size 4K
"""
)
parser.add_argument(
"prompt",
help="生成したい画像の説明(日本語可)"
)
parser.add_argument(
"output",
nargs="?",
default="generated_image.png",
help="出力ファイルパス(デフォルト: generated_image.png)"
)
parser.add_argument(
"--aspect-ratio", "-a",
choices=["1:1", "16:9", "9:16", "4:3", "3:4", "21:9"],
default="1:1",
help="アスペクト比(デフォルト: 1:1)"
)
parser.add_argument(
"--size", "-s",
choices=["1K", "2K", "4K"],
default=None,
help="画像サイズ(SDK がサポートしている場合: 1K, 2K, 4K)"
)
args = parser.parse_args()
generate_image(
prompt=args.prompt,
output_path=args.output,
aspect_ratio=args.aspect_ratio,
image_size=args.size,
)
if __name__ == "__main__":
main()
Claude Codeが必要に応じて画像を生成し、スライドに挿入するサイクルを自動化できました。
工夫⑤: PDF生成の自動化
最終的なPDF出力にはPuppeteerを使用しました。16:9のアスペクト比を維持したまま、背景色やJavaScriptの実行結果も含めてPDFに変換します。
await page.pdf({
path: 'slides.pdf',
width: '1920px',
height: '1080px',
printBackground: true,
margin: { top: 0, right: 0, bottom: 0, left: 0 },
preferCSSPageSize: false
});
これにより、ブラウザで表示した状態がそのままPDFになります。参加者への配布もスムーズでした。
一応こちらも Claude Skill 化して自動実行するようにしました。(あまり使いはしませんでしたが…)
振り返り
うまくいったこと
-
ルールを先に決めたことで統一された出力: rules.mdでレイアウト・色・フォントを事前定義したことで、Claude Codeが一貫したデザインを維持できました
-
画像生成のSkill化: Gemini 3 Pro ImageをClaude Skillとして定義したことで、AIが必要に応じて画像を生成→スライドに挿入のサイクルを自動化できました
-
HTMLの相性の良さ: HTMLはAIが得意な出力形式です。1発である程度高精度なものが得られました
-
伝えたい内容を盛り込めた: plot.mdで内容を先に固めたため、スライド作成時に迷うことがありませんでした
-
参加者の準備を最小化: PDF配布で環境依存なし、ハンズオンは各自の環境で行えるものとしました
-
再利用可能な資産の構築: rules.mdや画像生成Skill、PDF生成スクリプトなど、次回以降のスライド作成にも活用できる環境と知見が整いました
改善点
-
ファイルサイズ上限問題: slides.htmlが肥大化しました。Claude CodeのReadツールの上限を超え、ファイル全体を読み込めなくなりました。長いスライドの場合は分割が必要です
-
HTMLタグによるトークン消費: HTMLタグが多くトークンを消費している可能性があります。(わかっていたことではありますが、)Markdown系ツール(Marp等)との比較検討が必要かもしれません
まとめ
「Claude CodeでClaude Codeを学ぶ資料を作る」というメタ的な実践を通じて、コンテキストエンジニアリングの重要性を実感しました。
ポイント:
- 先に文脈を整える(要件整理 → 計画化 → タスク化)
- 小さく分割して依頼する
- ルールを明文化してAIに守らせる
AIコーディングツールは「使う → 共有 → 改善 → 標準化」のサイクルを組織で回すことで、より効果的に活用できます。この記事が、皆さんのAI活用の一助となれば幸いです。
明日は @kida_hironari さんの記事です。お楽しみに!

