JAWS DAYS 2026の登壇テンプレートから、Kiro CLI + Marpでスライドを作ってみた

JAWS DAYS 2026の登壇テンプレートから、Kiro CLI + Marpでスライドを作ってみた

JAWS DAYS 2026の公式PPTテンプレートをAIで解析し、Marpで再現を試みました。Kiro CLIを活用したPythonによるデザイン抽出や、視認性を高めるCSS「座布団」テクニックなど、AIとのペアプロでスライドを半自動構築した工程を紹介します。
2026.02.22

先日、「Claude Desktopでパワーポイントスライドを作成する記事」を読み、AIでテンプレートを活かしたスライドを作る体験に触発されました。

https://dev.classmethod.jp/articles/claude-opus-4-6-powerpoint-creation-support/

ちょうど自分も、2週間後に控えた JAWS DAYS 2026 で登壇予定があり、配布された公式テンプレートからスライドを作成する必要があったため、さっそくこの手法を試してみました。

せっかくならAIでスライド生成できないかと考え、最初はNotebookLM等の「よしなにやってくれる系」のツールを試しました。ただ、思ったレイアウトにならなかったり、微調整が効かなかったりと、ブラックボックスゆえの壁にぶつかりました。

そこで方針を変えました。AIには解析やコード生成をアシストしてもらいつつ、出力自体はMarp(Markdown)という中身の見える仕組みでコントロールする。Kiro CLI + Marpの組み合わせです。

完全自動生成ではなく、AIとのペアプロによる半自動構築です。手戻りが少なく、意図通りに動かせます。テンプレートの解析からカスタムテーマ作成、スライド生成まで対話的に進めることができました。

awsdays2026_marp_v5

本記事では、その手順を紹介します。

前提環境

  • テンプレートファイル(.pptx)が手元にある
    • PDFエクスポート版もあると、スタイルの解析が捗ります

Docker+EC2(Amazon Linux 2023)

本記事ではEC2(Amazon Linux 2023)上でDocker経由でツールを実行しています。python-pptx、PyMuPDF等のPythonライブラリもMarp CLIもすべてDockerコンテナ内で動かしています。

端末上に直接インストールしても動作しますが、EC2やコンテナを使い捨てで利用することで、開発環境をクリーンに保てます。

Kiroへの指示も「Dockerで実行して」の一言で済むので、対話の流れもスムーズでした。

Kiro CLIについて

本記事ではKiro CLI v1.26.2、Proライセンスで、モデルは Claude Opus 4.6を使用しました。

VS Code Remote SSHでEC2に接続し、ターミナルからKiro CLIを利用しています。

https://dev.classmethod.jp/articles/kiro-cli-ec2-amazon-linux-2023-install/

全体の流れ

0. テンプレート入手 → 公式PPTXとPDFを作業ディレクトリに配置
1. テンプレート解析(python-pptx)→ レイアウト構造・画像抽出
2. PDF解析(PyMuPDF)→ フォント・色・サイズの特定
3. Marpカスタムテーマ作成(CSS)→ 抽出素材を組み込み
4. スライド本文作成(Markdown)
5. Marp CLIでビルド(Docker)→ HTML / PPTX 出力

Step 0: 公式テンプレートの入手

JAWS DAYS 2026では、登壇者向けにスライドテンプレート(PPTX)が提供されています。テンプレートには以下が含まれています:

  • タイトルスライド用の背景画像(右上にイベントロゴ等の表示あり)
  • 通常スライド用の背景画像
  • フォント・配色の指定

テンプレートの注意事項として「タイトルスライドの右上に配置してある表示については変更しないでください」とあります。本記事の手法では背景画像をそのまま抽出して使うため、この制約は自然に維持されます。

テンプレート注意点

テンプレートのPPTXファイルと、あればPDFエクスポート版を作業ディレクトリに配置しておきます。


Step 1: テンプレートのレイアウト構造を解析

docker run --rm -v "$(pwd):/work" python:3.12-slim bash -c \
  "pip install python-pptx -q && python3 /work/analyze_template.py"

analyze_template.py

from pptx import Presentation

prs = Presentation('/work/template.pptx')
print(f'Slide size: {prs.slide_width}, {prs.slide_height}')
print(f'Slides: {len(prs.slides)}')

# レイアウト一覧
for i, layout in enumerate(prs.slide_layouts):
    print(f'Layout {i}: {layout.name} ({len(layout.placeholders)} placeholders)')
    for ph in layout.placeholders:
        print(f'  PH {ph.placeholder_format.idx}: {ph.name} ({ph.placeholder_format.type})')

# スライド内容
for i, slide in enumerate(prs.slides):
    print(f'Slide {i}: layout={slide.slide_layout.name}, shapes={len(slide.shapes)}')
    for s in slide.shapes:
        txt = s.text[:60] if s.has_text_frame else '(no text)'
        print(f'  {s.shape_type}: {s.name} - {txt}')

出力例(JAWS DAYS 2026)

Layout 0: タイトル スライド (5 placeholders)
  PH 0: タイトル 1 (CENTER_TITLE)
  PH 1: 字幕 2 (SUBTITLE)
Layout 1: タイトルとコンテンツ (5 placeholders)
  PH 0: タイトル 1 (TITLE)
  PH 1: コンテンツ プレースホルダー 2 (OBJECT)
Layout 4: 1_セクション見出し (4 placeholders)
  PH 0: タイトル 1 (TITLE)
...

レイアウト名とプレースホルダー構成を把握し、どのレイアウトをどのスライドタイプに使うか決めます。


Step 2: 画像素材を抽出

extract_assets.py

from pptx import Presentation
import os, hashlib

prs = Presentation('/work/template.pptx')
os.makedirs('/work/assets', exist_ok=True)

def save_img(blob, content_type, prefix):
    ext = content_type.split('/')[-1].replace('jpeg', 'jpg')
    h = hashlib.md5(blob).hexdigest()[:8]
    name = f'{prefix}_{h}.{ext}'
    with open(f'/work/assets/{name}', 'wb') as f:
        f.write(blob)
    print(f'  {name} ({len(blob)} bytes)')

# スライドマスター(共通背景)
for rel in prs.slide_masters[0].part.rels.values():
    if 'image' in rel.reltype:
        save_img(rel.target_part.blob, rel.target_part.content_type, 'master')

# レイアウト(レイアウト固有の背景)
for i, layout in enumerate(prs.slide_layouts):
    for rel in layout.part.rels.values():
        if 'image' in rel.reltype:
            save_img(rel.target_part.blob, rel.target_part.content_type, f'layout{i}')

# スライド(ロゴ・写真等)
for i, slide in enumerate(prs.slides):
    for shape in slide.shapes:
        if shape.shape_type == 13:  # PICTURE
            save_img(shape.image.blob, shape.image.content_type,
                     f'slide{i}_{shape.name.replace(" ", "_")}')
docker run --rm -v "$(pwd):/work" python:3.12-slim bash -c \
  "pip install python-pptx -q && python3 /work/extract_assets.py"

抽出後、用途がわかる名前にリネームしておきます。

cp assets/master_59d01390.png assets/bg_normal.png    # 通常スライド背景
cp assets/layout0_5359490e.png assets/bg_title.png    # タイトルスライド背景
cp assets/layout0_49552750.png assets/logo_title.png  # タイトル用ロゴ
  • master_* = 全レイアウト共通の背景画像
  • layout0_* = タイトルスライド固有の背景
  • 同じハッシュの画像は同一ファイルです(重複排除の目安)

Step 3: PDF解析でフォント・色・サイズを特定

テンプレートをPDFエクスポートし、PyMuPDFで解析します。

docker run --rm -v "$(pwd):/work" python:3.12-slim bash -c \
  "pip install pymupdf -q && python3 /work/analyze_pdf.py"

analyze_pdf.py

import fitz

doc = fitz.open("/work/template.pdf")
for i, page in enumerate(doc):
    pix = page.get_pixmap(dpi=150)
    pix.save(f"/work/assets/template_page{i}.png")  # 目視確認用

    print(f"Page {i}: {pix.width}x{pix.height}")
    for b in page.get_text("dict")["blocks"]:
        for line in b.get("lines", []):
            for span in line["spans"]:
                txt = span["text"].strip()
                if txt:
                    print(f"  [{span['size']:.1f}pt {span['font']}]"
                          f" color=#{span['color']:06x} \"{txt[:50]}\"")

出力例

Page 0: 2000x1125
  [36.0pt YuGothic-Bold] color=#424242 "JAWS DAYS 2026"
  [59.9pt YuGothic-Light] color=#424242 "登壇資料用テンプレート"
  [23.8pt YuGothic-Regular] color=#424242 "デザイン班 鮫肌 鮫男"

読み取れるデザインルール

要素 フォント サイズ ウェイト
イベント名 YuGothic 36pt Bold #424242
メインタイトル YuGothic 60pt Light #424242
サブタイトル YuGothic 24pt Regular #424242
スライドタイトル YuGothic 44pt Light #424242
本文 YuGothic 28pt Regular #424242
ハッシュタグ YuGothic 18pt Regular #424242

Step 4: Marpカスタムテーマ(CSS)を作成

Step 1〜3で得た背景画像・フォント・配色をCSSに反映しました。

mytheme.css

/* @theme mytheme */
@import 'default';

section {
  font-family: 'Yu Gothic', 'YuGothic', 'Noto Sans JP', sans-serif;
  background-image: url('./assets/bg_normal.png');
  background-size: 80%;
  background-repeat: no-repeat;
  background-position: center center;
  color: #424242;
  padding: 50px 60px 40px;
}

section h1 {
  color: #424242;
  font-weight: 300;  /* Light */
  font-size: 1.4em;
}

section p, section li {
  font-weight: 400;  /* Regular */
  font-size: 0.85em;
}

/* タイトル・セクション区切り共通 */
section.title, section.section {
  background-image: url('./assets/bg_title.png');
  background-size: 80%;
  background-repeat: no-repeat;
  background-position: center center;
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
}

section.title h1, section.section h1 {
  font-weight: 300;
  font-size: 1.8em;
}

/* テーブル */
table th {
  background-color: #424242;
  color: #fff;
}
  • /* @theme mytheme */ が必須です(Marpがテーマ名として認識します)
  • @import 'default' でMarpデフォルトテーマを継承しています
  • background-size: 80% で画像の上下見切れを防止しています

PPTX画像化を逆手に取る:Webフォントの焼き付け

Marp生成のPPTXはレンダリング結果を画像として埋め込むため、どんな環境のPCで開いてもフォントやレイアウトが崩れません。これを活かして、テンプレート指定のフォントがない環境でもGoogle Fontsから読み込んで利用できました。

/* テンプレート指定フォントがない環境向け:Webフォントで代替 */
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@300;400;700&family=Roboto:wght@300;400;700&display=swap');
section { font-family: 'Roboto', 'Noto Sans JP', sans-serif; }

背景画像の上で文字を読みやすくする:座布団テクニック

イベントテンプレートの背景画像は装飾が多く、そのままだと文字が埋もれがちです。MarpはChromium上でレンダリングするため、CSSの装飾がそのままスライドに反映されます。これを活かして、文字の背後に半透明の帯(座布団)を敷くと視認性が大幅に改善します。

/* タイトルスライドのh1:黒の半透明座布団 + 白文字 */
section.title h1 {
  color: #ffffff;
  background-color: rgba(0, 0, 0, 0.55);
  display: inline-block;
  padding: 12px 36px;
  border-radius: 8px;
}

/* サブタイトル・登壇者情報:白の半透明座布団 + ダーク文字 */
section.title h2 {
  color: #333333;
  background-color: rgba(255, 255, 255, 0.85);
  display: inline-block;
  padding: 8px 24px;
  border-radius: 4px;
}

h1を黒帯、h2/pを白帯にすることで情報の階層にコントラストがつき、背景画像の存在感を残しつつ文字がくっきり読めるようになります。text-shadow-webkit-text-stroke による縁取りも有効ですが、座布団が最も安定して読みやすい結果になりました。


Step 5: スライド本文をMarkdownで作成

slides.md

---
marp: true
theme: mytheme
paginate: true
size: 16:9
---

<!-- _class: title -->

# セッションタイトル
## サブタイトル

イベント名 | 日時
**登壇者名**

---

# 通常スライド

- 箇条書き1
- 箇条書き2

---

<!-- _class: section -->

# セクション区切り

---

# コンテンツスライド

| 項目 | 値 |
|---|---|
| A | B |

Marp Markdown記法

記法 用途
--- スライド区切り
<!-- _class: title --> CSSクラスを適用
![bg](image.png) 背景画像(個別指定)
<span class="red">text</span> インラインHTML(--htmlフラグ必要)

Step 6: Marp CLIでビルド(Docker)

HTML出力

docker run --rm \
  -e MARP_USER="$(id -u):$(id -g)" \
  -v "$(pwd):/home/marp/app" \
  marpteam/marp-cli \
  slides.md --theme mytheme.css --html --allow-local-files \
  -o output/slides.html

PPTX出力

docker run --rm \
  -e MARP_USER="$(id -u):$(id -g)" \
  -v "$(pwd):/home/marp/app" \
  marpteam/marp-cli \
  slides.md --theme mytheme.css --pptx --allow-local-files \
  -o output/slides.pptx
  • -e MARP_USER="$(id -u):$(id -g)" — パーミッションエラー防止
  • --allow-local-files — ローカル画像参照に必須
  • --html — Markdown内の <span> 等を有効化

Kiro CLIでの進め方

上記Step 1〜6はすべてKiro CLIとの対話で実行しました。Pythonスクリプトの作成もCSS生成もKiroに任せられるので、「何を解析するか」「どう再現するか」の判断に集中できました。

プロンプト例

# テンプレート解析(Step 1-2を一度に)
作業ディレクトリの template.pptx を解析して。
レイアウト構造と埋め込み画像を一覧化し、背景画像はassetsに抽出して。
Dockerの隔離環境でpython-pptxを使って。

# PDF解析(Step 3)
template.pdf をPyMuPDFで解析して、フォント名・サイズ・色・ウェイトを一覧化して。

# カスタムテーマ作成(Step 4)
抽出した背景画像とPDF解析結果をもとに、Marp用のカスタムCSSテーマを作成して。

# スライド生成(Step 5)
SLIDE_SPEC.md に基づいて、Marp形式のslides.mdを作成して。

# ビルド(Step 6)
Marp CLIのDockerイメージでHTMLとPPTXを生成して。
ビルドはまだ後で、マークダウンが全て終了した後。

# 可否判断を先に聞くと手戻りが減る
Marpの標準機能だけで、背景画像の上に半透明のボックス(座布団)を配置することは可能?
それとも、個別にCSSを書かないと実現できないかな?

# 「どう思う?」でトレードオフの整理を任せる
全スライドに背景画像を適用するのは、文字の読みやすさを考えると欲張りすぎ(盛り込みすぎ)?
白背景のスライドも混ぜたほうがいいと思う?

# 修正指示は「問題」+「意図」で伝えると精度が上がる
「自動生成」という言葉は、別の表現に改善できない?
完全に放置で出来上がるわけではなく、AIと対話しながら作る「共同作業」であることを強調したい。


まとめ

公式PPTXテンプレートの解析から、カスタムCSS作成、Webフォント適用、座布団による視認性改善、そしてHTML/PPTXビルドまで、すべてKiro CLIとの対話で進めることができました。

Kiro + Marpの面白さは「一緒に作る」感覚にあります。完全自動生成の「思ってたのと違う」を繰り返すより、対話しながら判断を重ねるほうが結果的に手戻りが少なくなりました。仕様書もスライドもMarkdownなので、Kiroとの対話で構成や表現を推敲し、そのままビルドに反映できるのも大きな利点です。

AIでスライドを作る選択肢が増えてきました。ぜひKiro + Marpも試してみてください。

この記事をシェアする

FacebookHatena blogX

関連記事