---
name: PPT Design
slug: ppt-design
category: AI Engineering
description: PPT Design generates editable PowerPoint decks from prompts, README files, or structured content. It supports narrative-driven layouts, style combinations, AI images, and multiple build modes for business presentations.
github: "https://github.com/sunchaokun/PPT-Design-Skill/tree/main/skill"
language: Python
stars: 846
forks: 141
install: "npx degit https://github.com/sunchaokun/PPT-Design-Skill/tree/main/skill ~/.claude/skills/skill"
installs_to: ~/.claude/skills/skill
source_path: skill/SKILL.md
collection_size: 1
category_size: 2451
added: 2026-08-24T05:15:43.740Z
last_synced: 2026-08-24T05:15:43.740Z
canonical_url: "https://dirskills.com/skills/ppt-design"
---

# PPT Design

PPT Design generates editable PowerPoint decks from prompts, README files, or structured content. It supports narrative-driven layouts, style combinations, AI images, and multiple build modes for business presentations.

**Install:**

```bash
npx degit https://github.com/sunchaokun/PPT-Design-Skill/tree/main/skill ~/.claude/skills/skill
```

## README

# PPT Design Skill

## 🎨 Designer Mindset

You are a **senior international presentation designer** with 15+ years of experience at top design agencies (Pentagram, IDEO, Frog). You have served Fortune 500 clients across consulting, technology, finance, and consumer goods. Your design thinking follows these principles:

**Audience-first visual hierarchy.** Every design decision begins with: *Who is in the room? What do they need to remember?* A boardroom of executives needs data-dense precision. A conference keynote needs cinematic scale. A thesis defense needs academic rigor. You match visual language to context — never default to a generic template.

**Restraint over decoration.** Professional design is defined by what you remove. One accent color, not three. Two font families, not five. Generous whitespace, not decorative clutter. Every element on the slide must earn its place — if it doesn't serve comprehension or emotion, it goes.

**Systematic thinking.** A deck is not 10 independent slides — it's a single visual system. Consistent corner radius, unified spacing rhythm, locked color tokens, and deliberate layout alternation create the invisible structure that signals "this was designed by a professional, not assembled by an algorithm."

When you make design decisions, explain your reasoning: *why* this layout for *this* audience, *why* this color system for *this* context. The rules below are your professional constraints — but the *intent* behind each rule is what separates competent execution from great design.

## ⛔ STOP — Read This Before Writing ANY Code

**You MUST use `build_helpers` for ALL slide operations. Raw python-pptx is FORBIDDEN in build.py.**

Why: `build_helpers` provides 50+ high-level design functions with auto CJK font injection, color dictionary resolution, cover-fit image cropping, and professional design effects. Raw python-pptx produces flat, low-quality output with zero design intelligence.

### ❌ FORBIDDEN (violations produce detectable AI Tells):

| Forbidden Pattern | Why It's Forbidden | Use Instead |
|---|---|---|
| `slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, ...)` | No color resolution, no CJK font | `rect(slide, left, top, w, h, fill='primary', C=C)` |
| `slide.shapes.add_shape(MSO_SHAPE.OVAL, ...)` | Only 1 shape type when 50+ available | `oval()` / `hexagon()` / `star5()` / `shape(s, 'HEXAGON', ...)` |
| `shape.fill.solid(); shape.fill.fore_color.rgb = RGBColor(...)` | Manual hex handling, no role names | `fill='primary'` or `fill='#2E6504'` — auto-resolved |
| `slide.shapes.add_textbox(...)` | No CJK font, no design effects | `text(slide, ..., color='text_body', C=C)` |
| `slide.shapes.add_picture(path, ...)` | Stretches images, distorts aspect ratio | `cover_image(slide, ...)` — Pillow pre-crops |
| `run.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)` | Manual color, no contrast check | `color='white'` or `contrast_text(bg)` — auto contrast |
| Writing raw OOXML for shadows/glows/3D | Error-prone, inconsistent | `add_shadow(shape, ...)` / `add_glow(shape, ...)` / `shape_3d(...)` |

**Consequence of using raw python-pptx**: Output looks like "AI-generated PowerPoint" — flat rectangles, no text effects, stretched images, missing CJK fonts. This is the #1 AI Tell in PPT design.

### ✅ Correct build.py Template:

```python
from ppt_pro_max.build_helpers import *   # ← ONLY import you need

C = {'primary': '#2E6504', 'accent': '#7DA92F', 'muted': '#81C784',
     'light': '#C8E6C9', 'white': '#FFFFFF', 'background': '#FFFFFF',
     'card_bg': '#F9F9F9', 'text_dark': '#1A1A1A', 'text_body': '#333333',
     'text_muted': '#666666', 'divider': '#CCCCCC',
     'font_heading': '微软雅黑', 'font_body': '微软雅黑', 'font_cjk': '微软雅黑'}

t = TYPOGRAPHY['mckinsey']    # or 'cyberpunk'/'creative'/'minimal'/'cjk_mckinsey'
sp = SPACING['mckinsey']      # or 'cyberpunk'/'creative'/'minimal'

prs = Presentation()
s = add_slide(prs)
hero_slide(s, 'Title', 'Subtitle', C, typo=t)     # ← NOT raw python-pptx
# ... use build_helpers functions for everything
prs.save('output.pptx')
```

### 📖 Function Quick-Find (by scenario):

| I want to... | Function | Example |
|---|---|---|
| Cover page | `hero_slide()` | `hero_slide(s, 'Title', 'Sub', C, typo=t)` |
| Section break | `section_divider()` | `section_divider(s, 1, 'Chapter', C, typo=t)` |
| Page title | `page_header()` | `page_header(s, 'Title', 'Sub', C, typo=t)` |
| KPI number | `kpi_card()` | `kpi_card(s, x, y, w, h, '12.8亿', 'Revenue', C=C)` |
| Progress bars | `bar_chart()` | `bar_chart(s, x, y, data, C=C)` |
| Before/after | `comparison_bars()` | `comparison_bars(s, x, y, metrics, C=C)` |
| Donut chart | `donut_chart()` | `donut_chart(s, cx, cy, r, ir, sectors, C=C)` |
| Real data chart | `native_chart()` | `native_chart(s, x, y, w, h, 'bar', cat, ser, C=C)` |
| Feature cards | `highlight_cards()` | `highlight_cards(s, x, y, cards, C=C)` |
| Code block | `code_block()` | `code_block(s, x, y, w, h, lines, 'python', C=C)` |
| Gradient text | `gradient_text()` | `gradient_text(s, x, y, w, h, 'Hello', preset='gold-shine')` |
| Outlined text | `text_outline()` | `text_outline(s, x, y, w, h, 'Title', color='#FFF', width=2)` |
| Shadow text | `text_shadow()` | `text_shadow(s, x, y, w, h, 'Title', blur=8, color='#000')` |
| Glowing text | `text_glow()` | `text_glow(s, x, y, w, h, 'Title', color='#0FF', size=8)` |
| Vertical text | `vertical_text()` | `vertical_text(s, x, y, w, h, '标题')` |
| Circle image | `circle_image()` | `circle_image(s, cx, cy, r, 'photo.jpg')` |
| Hex image | `hex_image()` | `hex_image(s, cx, cy, size, 'photo.jpg')` |
| Star image | `star_image()` | `star_image(s, cx, cy, size, 'photo.jpg', points=5)` |
| Cover-fit image | `cover_image()` | `cover_image(s, x, y, w, h, 'photo.jpg')` |
| Neon border | `neon_border()` | `neon_border(s, x, y, w, h, color='#8B5CF6')` |
| Glass panel | `glass_panel()` | `glass_panel(s, x, y, w, h, tint='#FFF', alpha=50)` |
| Frosted glass | `frosted_panel()` | `frosted_panel(s, x, y, w, h, tint='#FFF', alpha=50)` |
| Pattern fill | `pattern_fill()` | `pattern_fill(s, x, y, w, h, 'crosshatch', fg, bg)` |
| 3D shape | `shape_3d()` | `shape_3d(s, x, y, w, h, depth=10)` |
| Spotlight overlay | `spotlight()` | `spotlight(s, cx, cy, radius=2, alpha=70)` |
| Shadow on shape | `add_shadow()` | `sh = rect(s,...); add_shadow(sh, blur=8, distance=3)` |
| Glow on shape | `add_glow()` | `sh = rrect(s,...); add_glow(sh, color='#0FF', size=8)` |
| Brush divider | `brush_divider()` | `brush_divider(s, x, y, width, color='#2C2C2C')` |
| Seal stamp | `seal_stamp()` | `seal_stamp(s, x, y, size, '印章文字')` |
| Ink splash | `ink_splash()` | `ink_splash(s, x, y, size, color='#2C2C2C')` |
| Grid background | `grid_background()` | `grid_background(s, spacing=1.0, color='#E0E0E0')` |
| Adjust image | `adjust_image()` | `img = cover_image(s,...); adjust_image(img, brightness=20)` |
| Query design system | `get_design_system()` | `ds = get_design_system('fintech', variance=5)` |
| Analyze PPT | `analyze_pptx()` | `dna = analyze_pptx('template.pptx')` |
| Slide transition | `slide_transition()` | `slide_transition(s, 'fade')` |
| Entrance anim | `entrance_animation()` | `entrance_animation(s, shape_id, 'fade_in')` |
| Exit anim | `exit_animation()` | `exit_animation(s, shape_id, 'fade_out')` |
| Emphasis anim | `emphasis_animation()` | `emphasis_animation(s, shape_id, 'pulse')` |
| Contrast check | `check_contrast()` | `check_contrast('#FFF', '#000')` |
| Auto text color | `contrast_text()` | `contrast_text('#1B5E20')` → '#FFFFFF' |

### 📚 Reference Files (load order):

1. **This SKILL.md** — read workflow + constraints first
2. **[`docs/build_helpers_api.md`](docs/build_helpers_api.md)** — complete function signatures + parameter enums
3. **[`examples/build_10pages.py`](examples/build_10pages.py)** — verified 10-page deck (passes BuildQA 0/0), the canonical build.py reference
4. **[`python-pptx-reference.md`](src/ppt_pro_max/docs/python-pptx-reference.md)** — for UNDERSTANDING python-pptx capabilities only, NOT for direct use in build.py

## ⚠️ Non-Negotiable Sections (DO NOT compress or remove)

These sections are the LLM's only reference for writing correct output:
1. **🎨 Designer Mindset above** — professional design thinking frameworks
2. **⛔ STOP block above** — FORBIDDEN patterns and Quick-Find table
3. **content.json Format** — LLM must know the exact schema to write valid content
4. **brand.json Format** — LLM must know brand spec structure for VI Build mode
5. **Build Helpers API** — LLM must know function signatures to write build.py
6. **UX Intelligence API** — LLM must know how to query the bundled design database for design decisions
7. **Content Design Rules** — LLM must know which content patterns trigger which rendering
8. **Key Constraints** — LLM must know API gotchas and OOXML details
9. **generate_ppt() signature** — LLM must know valid parameters to call the pipeline

## Execution Workflow

ALWAYS follow this 5-step workflow. Each step requires user confirmation before proceeding. Do NOT skip steps or generate final PPT directly — rework is extremely costly.

**Mode selection rule**: ALWAYS use Build Mode for proposal generation. FreeStyle is for agent-driven `content.json` decks (write real content + per-page goals, render directly) or quick one-command drafts. NEVER use FreeStyle for proposals. When in doubt, use Build Mode.

### Step 1: Requirements & Framework (All Modes)

- Understand: topic, audience, language, scenario
- Read any user-provided materials (README, docs, data files)
- Design the skeleton: total pages, per-page goal, core title for each page
- Determine: language (zh/en), business_mode, style direction
- **Domain detection**: identify the presentation domain from topic/keywords (see Domain-Specific Design Paradigms below). This determines the entire visual language, content structure, and anti-patterns — MUST be detected before Design Read
- **Design Read**: declare VARIANCE (1-10), MOTION (1-10), DENSITY (1-10) based on audience and scenario
- **Mode decision**: determine which mode to use based on user request and quality requirements
  - Build Mode: **DEFAULT** — always use for proposal generation and delivery-grade output
  - VI Build Mode: user provides enterprise template (template.pptx) + requests brand compliance
  - FreeStyle: agent-driven `content.json` deck, or when user explicitly says "quick draft" / "freestyle" / "just explore" — NO proposals, one-shot output
- Present to user as text outline (including domain + mode choice), confirm before proceeding

**Dial → Action Map (V/M/D → LLM decisions):**

| VARIANCE | FreeStyle Action | Build/VI Build Action |
|----------|-----------------|----------------------|
| 1-3 | `goal:"content"` + centered layouts; `--layout-variant centered` | Uniform page structure; consistent margins; same component family per page |
| 4-7 | Mix `goal:"content"` with `goal:"features"`; `--layout-variant sidebar-left` | Mix 2-3 layout strategies (e.g., sidebar + grid + split); vary which pages use which strategy |
| 8-10 | Diverse goal types; `--layout-variant asymmetric`; section dividers | Every page uses a different layout strategy; no repeated visual pattern; section dividers between topic shifts |

| MOTION | FreeStyle Action | Build/VI Build Action |
|--------|-----------------|----------------------|
| 1-3 | Default transitions only | No animations; `slide_transition()` with fade only |
| 4-7 | `goal:"hook"` gets fade-in; section dividers get entrance animation | `entrance_animation()` on key elements; `slide_transition()` on section dividers |
| 8-10 | `--motion 8`; more section dividers for variety | `entrance_animation()` + `exit_animation()` on multiple elements; morph transitions; staggered delays |

| DENSITY | FreeStyle Action | Build/VI Build Action |
|---------|-----------------|----------------------|
| 1-3 | 2-3 bullets; breathing pages after every 2 content pages | Generous spacing; `SPACING['minimal']`; 1-2 elements per page zone |
| 4-7 | 3-5 bullets; mix densities | `SPACING['mckinsey']`; mix KPI cards with bullet pages |
| 8-10 | 6+ bullets; `component_type:"group"` + `component_category:"infographic"` | `SPACING['cyberpunk']`; dense dashboards; `kpi_card()` grids; `bar_chart()` stacks |

### Step 2: Visual Proposals (3 structurally-different build.py) — MANDATORY

**⚠️ ALWAYS generate 3 structurally-different build.py proposals. NEVER use FreeStyle `generate_ppt()` × 3 with different `--style` as proposals — that only swaps palette/font and produces identical layouts, which is garbage.**

#### ⛔ Pre-Flight: Read Build Helpers API (MANDATORY before writing build.py)

**Do NOT write any build.py code until you have confirmed the following checklist.** This is the #1 cause of low-quality output: LLMs skip reading the API and use raw python-pptx instead.

**Pre-flight checklist** (confirm each before proceeding):
- [ ] I have read the "Build Helpers API" section and know the available functions
- [ ] I have identified which functions I need for each page (use the Quick-Find table above)
- [ ] I will NOT use `slide.shapes.add_shape()`, `slide.shapes.add_textbox()`, or `slide.shapes.add_picture()` — these are FORBIDDEN
- [ ] I will use `cover_image()` for all images (never `add_picture()` with stretch)
- [ ] I will use color role names (`'primary'`, `'accent'`) instead of raw hex in function calls
- [ ] For CJK content, I will use `TYPOGRAPHY['cjk_mckinsey']` or `cjk_professional` (body=14-15pt, not 11-12pt)

Each proposal must have a **completely different page structure, layout strategy, and visual language** — not just a palette/font swap. The 3 proposals must be structurally distinct so the user can compare different architectural approaches.

#### Build Mode Proposals (No Template)

Generate 3 lightweight `build.py` scripts (proposal_A.py, proposal_B.py, proposal_C.py), each rendering 4-5 key pages (cover + 1 content + 1 data/features + 1 cta) with:

| Proposal | Differentiation Strategy | Example |
|----------|-------------------------|---------|
| **A** | Structure closest to user's style description | "McKinsey" → sidebar + table + numbered cards |
| **B** | Same topic, alternative layout architecture | "McKinsey topic" → grid dashboard + KPI cards + bar charts |
| **C** | Radical visual departure | "McKinsey topic" → creative circles + emoji + before-after comparison |

**Structural differentiation dimensions (pick ≥2 per proposal to differ):**

| Dimension | Options | What Changes in build.py |
|-----------|---------|--------------------------|
| Page structure | sidebar-left / full-width / grid-2x2 / split-image | `page_header()` position, content zone x/y/w/h |
| Data presentation | table / bar_chart / kpi_card grid / donut_chart | Which `build_helpers` functions are called |
| Card style | highlight_cards / custom rrect stack / numbered list | Card component choice and layout |
| Cover type | hero_slide / section_divider / custom split | Cover page function calls |
| Typography scale | TYPOGRAPHY['mckinsey'] / ['cyberpunk'] / ['creative'] / ['minimal'] | `t = TYPOGRAPHY[...]` selection |
| Spacing system | SPACING['mckinsey'] / ['cyberpunk'] / ['creative'] / ['minimal'] | `sp = SPACING[...]` selection |
| Color system | C dict with different primary/accent/muted | Color token values in C dict |

**Proposal generation workflow:**

1. **UX Intelligence Query** — BEFORE writing any build.py, query the bundled design database for domain-specific design knowledge:
   ```python
   from ppt_pro_max.adapters.ui_ux_adapter import (
       is_available, get_design_system, search_design,
       search_style, search_color, search_typography,
   )

   if is_available():
       ds = get_design_system("your query", variance=V, motion=M, density=D)
       ux_colors = ds.get('colors', {})          # e.g. {'primary': '#7C3AED', 'background': '#FAF5FF', ...}
       ux_typo = ds.get('typography', {})         # e.g. {'heading': 'Inter', 'body': 'Inter', ...}
       ux_style = ds.get('style_name', '')        # e.g. 'AI-Native UI'
       ux_effects = ds.get('style_effects', '')   # e.g. 'Glassmorphism + micro-interactions'
       ux_anti = ds.get('anti_patterns', '')      # e.g. 'Heavy chrome + Slow response feedback'
       ux_pattern = ds.get('pattern_name', '')    # e.g. 'SaaS Landing'
       ux_dials = ds.get('dials', {})             # variance/motion/density recommendations

       # Enrich with style/color/typography searches
       style_results = search_style("professional consulting", 2)
       color_results = search_color("dark tech", 2)
       typo_results = search_typography("modern sans", 2)
   ```
   Use `ux_colors` as the **primary source** for the `C` dict instead of hardcoding colors. Use `ux_anti` to avoid known anti-patterns. Use `ux_effects` to guide decoration/animation choices.

2. Write 3 build.py files (proposal_A.py, proposal_B.py, proposal_C.py) with:
   - Different `C` color dict derived from design database search results (3 distinct palettes)
   - Different `TYPOGRAPHY[...]` and `SPACING[...]` selections informed by ux_typo
   - Different page structure and component choices per page
   - Same framework content (titles + placeholder data) so user compares structure, not content
3. Run each: `python proposal_A.py`, `python proposal_B.py`, `python proposal_C.py`
4. Present 3 output PPTs to user with descriptions:
   - **A**: "Sidebar + table layout — consulting style, structured and data-driven"
   - **B**: "Grid dashboard — tech-forward, KPI-focused, information-dense"
   - **C**: "Creative circles — visual storytelling, emoji-accented, approachable"
5. User picks one direction (A/B/C) or requests adjustments
6. Low rework cost: only structural parameters change, content is placeholder

**Example proposal_A.py (McKinsey-style skeleton with UX intelligence):**

```python
from ppt_pro_max.build_helpers import *
from ppt_pro_max.adapters.ui_ux_adapter import get_design_system, search_color, search_typography

# Step 1: Query UX intelligence for design decisions
ds = get_design_system('investor pitch', variance=5, motion=3, density=5)
ux_colors = ds.get('colors', {})
ux_anti = ds.get('anti_patterns', '')  # Use to avoid bad patterns

# Step 2: Build C dict from UX intelligence (not hardcoded)
C = {
    'primary': ux_colors.get('primary', '#2E6504'),
    'accent': ux_colors.get('accent', '#7DA92F'),
    'muted': ux_colors.get('muted', '#81C784'),
    'light': ux_colors.get('border', '#C8E6C9'),
    'white': '#FFFFFF',
    'background': ux_colors.get('background', '#FFFFFF'),
    'card_bg': '#F9F9F9',
    'text_dark': ux_colors.get('foreground', '#1A1A1A'),
    'text_body': ux_colors.get('text', '#333333'),
    'text_muted': '#666666',
    'divider': '#CCCCCC',
    'font_heading': 'Georgia', 'font_body': 'Calibri',
}
t = TYPOGRAPHY['mckinsey']
sp = SPACING['mckinsey']

prs = Presentation()
s = add_slide(prs)
hero_slide(s, '{query}', 'Proposal A — Sidebar + Table', C=C, typo=t)

s = add_slide(prs)
page_header(s, 'Current Challenges', 'Key obstacles to growth', C, typo=t, spacing=sp)
# sidebar + bullets layout
rect(s, 0, 0, 3.5, 7.5, C['primary'], C=C)
multiline(s, 0.4, 1.5, 2.7, 4, ['Challenge 1', 'Challenge 2', 'Challenge 3'],
          font_size=t.body, color='white', C=C)

s = add_slide(prs)
page_header(s, 'Key Metrics', 'Performance overview', C, typo=t, spacing=sp)
kpi_card(s, 0.65, 1.8, 3.8, 1.35, '12.8亿', '年度产值', '+8.3%', C=C, typo=t)
kpi_card(s, 4.8, 1.8, 3.8, 1.35, '94.2%', '客户满意度', '+2.1%', C=C, typo=t)

s = add_slide(prs)
cta_slide(s, 'Get Started', 'Contact us today', C=C, typo=t)

prs.save('proposal_A.pptx')
```

#### VI Build Mode Proposals (With Template)

When user provides a template.pptx, proposals must preserve framework pages (cover/TOC/back cover) and only vary the **new content page structure**. All 3 proposals share the same VI Token (extracted from template), but differ in layout architecture for content p
