Initial commit: add all skills files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
249
pptx-generator/SKILL.md
Normal file
249
pptx-generator/SKILL.md
Normal file
@@ -0,0 +1,249 @@
|
||||
---
|
||||
name: pptx-generator
|
||||
description: "Generate, edit, and read PowerPoint presentations. Create from scratch with PptxGenJS (cover, TOC, content, section divider, summary slides), edit existing PPTX via XML workflows, or extract text with markitdown. Triggers: PPT, PPTX, PowerPoint, presentation, slide, deck, slides."
|
||||
license: MIT
|
||||
metadata:
|
||||
version: "1.0"
|
||||
category: productivity
|
||||
sources:
|
||||
- https://gitbrent.github.io/PptxGenJS/
|
||||
- https://github.com/microsoft/markitdown
|
||||
---
|
||||
|
||||
# PPTX Generator & Editor
|
||||
|
||||
## Overview
|
||||
|
||||
This skill handles all PowerPoint tasks: reading/analyzing existing presentations, editing template-based decks via XML manipulation, and creating presentations from scratch using PptxGenJS. It includes a complete design system (color palettes, fonts, style recipes) and detailed guidance for every slide type.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Task | Approach |
|
||||
|------|----------|
|
||||
| Read/analyze content | `python -m markitdown presentation.pptx` |
|
||||
| Edit or create from template | See [Editing Presentations](references/editing.md) |
|
||||
| Create from scratch | See [Creating from Scratch](#creating-from-scratch-workflow) below |
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| **Dimensions** | 10" x 5.625" (LAYOUT_16x9) |
|
||||
| **Colors** | 6-char hex without # (e.g., `"FF0000"`) |
|
||||
| **English font** | Arial (default), or approved alternatives |
|
||||
| **Chinese font** | Microsoft YaHei |
|
||||
| **Page badge position** | x: 9.3", y: 5.1" |
|
||||
| **Theme keys** | `primary`, `secondary`, `accent`, `light`, `bg` |
|
||||
| **Shapes** | RECTANGLE, OVAL, LINE, ROUNDED_RECTANGLE |
|
||||
| **Charts** | BAR, LINE, PIE, DOUGHNUT, SCATTER, BUBBLE, RADAR |
|
||||
|
||||
## Reference Files
|
||||
|
||||
| File | Contents |
|
||||
|------|----------|
|
||||
| [slide-types.md](references/slide-types.md) | 5 slide page types (Cover, TOC, Section Divider, Content, Summary) + additional layout patterns |
|
||||
| [design-system.md](references/design-system.md) | Color palettes, font reference, style recipes (Sharp/Soft/Rounded/Pill), typography & spacing |
|
||||
| [editing.md](references/editing.md) | Template-based editing workflow, XML manipulation, formatting rules, common pitfalls |
|
||||
| [pitfalls.md](references/pitfalls.md) | QA process, common mistakes, critical PptxGenJS pitfalls |
|
||||
| [pptxgenjs.md](references/pptxgenjs.md) | Complete PptxGenJS API reference |
|
||||
|
||||
---
|
||||
|
||||
## Reading Content
|
||||
|
||||
```bash
|
||||
# Text extraction
|
||||
python -m markitdown presentation.pptx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Creating from Scratch — Workflow
|
||||
|
||||
**Use when no template or reference presentation is available.**
|
||||
|
||||
### Step 1: Research & Requirements
|
||||
|
||||
Search to understand user requirements — topic, audience, purpose, tone, content depth.
|
||||
|
||||
### Step 2: Select Color Palette & Fonts
|
||||
|
||||
Use the [Color Palette Reference](references/design-system.md#color-palette-reference) to select a palette matching the topic and audience. Use the [Font Reference](references/design-system.md#font-reference) to choose a font pairing.
|
||||
|
||||
### Step 3: Select Design Style
|
||||
|
||||
Use the [Style Recipes](references/design-system.md#style-recipes) to choose a visual style (Sharp, Soft, Rounded, or Pill) matching the presentation tone.
|
||||
|
||||
### Step 4: Plan Slide Outline
|
||||
|
||||
Classify **every slide** as exactly one of the [5 page types](references/slide-types.md). Plan the content and layout for each slide. Ensure visual variety — do NOT repeat the same layout across slides.
|
||||
|
||||
### Step 5: Generate Slide JS Files
|
||||
|
||||
Create one JS file per slide in `slides/` directory. Each file must export a synchronous `createSlide(pres, theme)` function. Follow the [Slide Output Format](#slide-output-format) and the type-specific guidance in [slide-types.md](references/slide-types.md). Generate up to 5 slides concurrently using subagents if available.
|
||||
|
||||
**Tell each subagent:**
|
||||
1. File naming: `slides/slide-01.js`, `slides/slide-02.js`, etc.
|
||||
2. Images go in: `slides/imgs/`
|
||||
3. Final PPTX goes in: `slides/output/`
|
||||
4. Dimensions: 10" x 5.625" (LAYOUT_16x9)
|
||||
5. Fonts: Chinese = Microsoft YaHei, English = Arial (or approved alternative)
|
||||
6. Colors: 6-char hex without # (e.g. `"FF0000"`)
|
||||
7. Must use the theme object contract (see [Theme Object Contract](#theme-object-contract))
|
||||
8. Must follow the [PptxGenJS API reference](references/pptxgenjs.md)
|
||||
|
||||
### Step 6: Compile into Final PPTX
|
||||
|
||||
Create `slides/compile.js` to combine all slide modules:
|
||||
|
||||
```javascript
|
||||
// slides/compile.js
|
||||
const pptxgen = require('pptxgenjs');
|
||||
const pres = new pptxgen();
|
||||
pres.layout = 'LAYOUT_16x9';
|
||||
|
||||
const theme = {
|
||||
primary: "22223b", // dark color for backgrounds/text
|
||||
secondary: "4a4e69", // secondary accent
|
||||
accent: "9a8c98", // highlight color
|
||||
light: "c9ada7", // light accent
|
||||
bg: "f2e9e4" // background color
|
||||
};
|
||||
|
||||
for (let i = 1; i <= 12; i++) { // adjust count as needed
|
||||
const num = String(i).padStart(2, '0');
|
||||
const slideModule = require(`./slide-${num}.js`);
|
||||
slideModule.createSlide(pres, theme);
|
||||
}
|
||||
|
||||
pres.writeFile({ fileName: './output/presentation.pptx' });
|
||||
```
|
||||
|
||||
Run with: `cd slides && node compile.js`
|
||||
|
||||
### Step 7: QA (Required)
|
||||
|
||||
See [QA Process](references/pitfalls.md#qa-process).
|
||||
|
||||
### Output Structure
|
||||
|
||||
```
|
||||
slides/
|
||||
├── slide-01.js # Slide modules
|
||||
├── slide-02.js
|
||||
├── ...
|
||||
├── imgs/ # Images used in slides
|
||||
└── output/ # Final artifacts
|
||||
└── presentation.pptx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Slide Output Format
|
||||
|
||||
Each slide is a **complete, runnable JS file**:
|
||||
|
||||
```javascript
|
||||
// slide-01.js
|
||||
const pptxgen = require("pptxgenjs");
|
||||
|
||||
const slideConfig = {
|
||||
type: 'cover',
|
||||
index: 1,
|
||||
title: 'Presentation Title'
|
||||
};
|
||||
|
||||
// MUST be synchronous (not async)
|
||||
function createSlide(pres, theme) {
|
||||
const slide = pres.addSlide();
|
||||
slide.background = { color: theme.bg };
|
||||
|
||||
slide.addText(slideConfig.title, {
|
||||
x: 0.5, y: 2, w: 9, h: 1.2,
|
||||
fontSize: 48, fontFace: "Arial",
|
||||
color: theme.primary, bold: true, align: "center"
|
||||
});
|
||||
|
||||
return slide;
|
||||
}
|
||||
|
||||
// Standalone preview - use slide-specific filename
|
||||
if (require.main === module) {
|
||||
const pres = new pptxgen();
|
||||
pres.layout = 'LAYOUT_16x9';
|
||||
const theme = {
|
||||
primary: "22223b",
|
||||
secondary: "4a4e69",
|
||||
accent: "9a8c98",
|
||||
light: "c9ada7",
|
||||
bg: "f2e9e4"
|
||||
};
|
||||
createSlide(pres, theme);
|
||||
pres.writeFile({ fileName: "slide-01-preview.pptx" });
|
||||
}
|
||||
|
||||
module.exports = { createSlide, slideConfig };
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Theme Object Contract (MANDATORY)
|
||||
|
||||
The compile script passes a theme object with these **exact keys**:
|
||||
|
||||
| Key | Purpose | Example |
|
||||
|-----|---------|---------|
|
||||
| `theme.primary` | Darkest color, titles | `"22223b"` |
|
||||
| `theme.secondary` | Dark accent, body text | `"4a4e69"` |
|
||||
| `theme.accent` | Mid-tone accent | `"9a8c98"` |
|
||||
| `theme.light` | Light accent | `"c9ada7"` |
|
||||
| `theme.bg` | Background color | `"f2e9e4"` |
|
||||
|
||||
**NEVER use other key names** like `background`, `text`, `muted`, `darkest`, `lightest`.
|
||||
|
||||
---
|
||||
|
||||
## Page Number Badge (REQUIRED)
|
||||
|
||||
All slides **except Cover Page** MUST include a page number badge in the bottom-right corner.
|
||||
|
||||
- **Position**: x: 9.3", y: 5.1"
|
||||
- Show current number only (e.g. `3` or `03`), NOT "3/12"
|
||||
- Use palette colors, keep subtle
|
||||
|
||||
### Circle Badge (Default)
|
||||
|
||||
```javascript
|
||||
slide.addShape(pres.shapes.OVAL, {
|
||||
x: 9.3, y: 5.1, w: 0.4, h: 0.4,
|
||||
fill: { color: theme.accent }
|
||||
});
|
||||
slide.addText("3", {
|
||||
x: 9.3, y: 5.1, w: 0.4, h: 0.4,
|
||||
fontSize: 12, fontFace: "Arial",
|
||||
color: "FFFFFF", bold: true,
|
||||
align: "center", valign: "middle"
|
||||
});
|
||||
```
|
||||
|
||||
### Pill Badge
|
||||
|
||||
```javascript
|
||||
slide.addShape(pres.shapes.ROUNDED_RECTANGLE, {
|
||||
x: 9.1, y: 5.15, w: 0.6, h: 0.35,
|
||||
fill: { color: theme.accent },
|
||||
rectRadius: 0.15
|
||||
});
|
||||
slide.addText("03", {
|
||||
x: 9.1, y: 5.15, w: 0.6, h: 0.35,
|
||||
fontSize: 11, fontFace: "Arial",
|
||||
color: "FFFFFF", bold: true,
|
||||
align: "center", valign: "middle"
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `pip install "markitdown[pptx]"` — text extraction
|
||||
- `npm install -g pptxgenjs` — creating from scratch
|
||||
- `npm install -g react-icons react react-dom sharp` — icons (optional)
|
||||
392
pptx-generator/references/design-system.md
Normal file
392
pptx-generator/references/design-system.md
Normal file
@@ -0,0 +1,392 @@
|
||||
# Design System
|
||||
|
||||
## Color Palette Reference
|
||||
|
||||
| # | Name | Colors | Style | Use Cases | Tips |
|
||||
|---|------|--------|-------|-----------|------|
|
||||
| 1 | Modern & Wellness | `#006d77` `#83c5be` `#edf6f9` `#ffddd2` `#e29578` | Fresh, soothing | Healthcare, counseling, skincare, yoga/spa | Deep teal for titles, light pink for background |
|
||||
| 2 | Business & Authority | `#2b2d42` `#8d99ae` `#edf2f4` `#ef233c` `#d90429` | Formal, classic | Annual reports, financial analysis, corporate intro, government | Deep blue for professionalism, bright red to highlight data |
|
||||
| 3 | Nature & Outdoors | `#606c38` `#283618` `#fefae0` `#dda15e` `#bc6c25` | Grounded, earthy | Outdoor gear, environmental, agriculture, historical culture | Dark green base, cream text |
|
||||
| 4 | Vintage & Academic | `#780000` `#c1121f` `#fdf0d5` `#003049` `#669bbc` | Classic, scholarly | Academic lectures, history reviews, museums, heritage brands | Strong contrast between deep red and deep blue |
|
||||
| 5 | Soft & Creative | `#cdb4db` `#ffc8dd` `#ffafcc` `#bde0fe` `#a2d2ff` | Dreamy, candy-toned | Mother & baby, desserts, women's fashion, kindergarten | Use dark gray or black for text |
|
||||
| 6 | Bohemian | `#ccd5ae` `#e9edc9` `#fefae0` `#faedcd` `#d4a373` | Gentle, muted | Wedding planning, home decor, organic food, slow living | Cream background, green-brown accents |
|
||||
| 7 | Vibrant & Tech | `#8ecae6` `#219ebc` `#023047` `#ffb703` `#fb8500` | High energy, sporty | Sports events, gyms, startup pitches, youth education | Deep blue for stability, orange as focal accent |
|
||||
| 8 | Craft & Artisan | `#7f5539` `#a68a64` `#ede0d4` `#656d4a` `#414833` | Rustic, coffee-toned | Coffee shops, handicrafts, traditional culture, bakery | Suited for paper/leather textures |
|
||||
| 9 | Tech & Night | `#000814` `#001d3d` `#003566` `#ffc300` `#ffd60a` | Deep, luminous | Tech launches, astronomy, night economy, luxury automobiles | Must use dark mode |
|
||||
| 10 | Education & Charts | `#264653` `#2a9d8f` `#e9c46a` `#f4a261` `#e76f51` | Clear, logical | Statistical reports, education, market analysis, general business | Perfect chart color scheme |
|
||||
| 11 | Forest & Eco | `#dad7cd` `#a3b18a` `#588157` `#3a5a40` `#344e41` | Monochrome gradient, forest | Landscape design, ESG reports, environmental causes, botanical | Monochrome palette is safe and cohesive |
|
||||
| 12 | Elegant & Fashion | `#edafb8` `#f7e1d7` `#dedbd2` `#b0c4b1` `#4a5759` | Muted, Morandi tones | Haute couture, art galleries, beauty brands, magazine style | Negative space is key |
|
||||
| 13 | Art & Food | `#335c67` `#fff3b0` `#e09f3e` `#9e2a2b` `#540b0e` | Rich, vintage-poster | Food documentaries, art exhibitions, ethnic themes, vintage restaurants | Works well with large color blocks |
|
||||
| 14 | Luxury & Mysterious | `#22223b` `#4a4e69` `#9a8c98` `#c9ada7` `#f2e9e4` | Cool, purple-toned | Jewelry showcases, hotel management, high-end consulting, psychology | Purple evokes premium atmosphere |
|
||||
| 15 | Pure Tech Blue | `#03045e` `#0077b6` `#00b4d8` `#90e0ef` `#caf0f8` | Futuristic, clean | Cloud/AI, water/ocean, hospitals, clean energy | Deep ocean to sky gradient |
|
||||
| 16 | Coastal Coral | `#0081a7` `#00afb9` `#fdfcdc` `#fed9b7` `#f07167` | Refreshing, summery | Travel, summer events, beverage brands, ocean themes | Teal and coral as complementary focal colors |
|
||||
| 17 | Vibrant Orange Mint | `#ff9f1c` `#ffbf69` `#ffffff` `#cbf3f0` `#2ec4b6` | Bright, cheerful | Children's events, promotional posters, FMCG, social media | Orange grabs attention, mint feels fresh |
|
||||
| 18 | Platinum White Gold | `#0a0a0a` `#0070F3` `#D4AF37` `#f5f5f5` `#ffffff` | Premium, professional | Agent products, corporate websites, fintech, luxury brands | White-gold base, blue for action, gold for emphasis |
|
||||
|
||||
---
|
||||
|
||||
### Agent Design System — Full Color Scale
|
||||
|
||||
Based on the Platinum White-Gold Theme design tokens. Provides complete color scales for fine-grained design work.
|
||||
|
||||
#### White Scale (Backgrounds & Light Surfaces)
|
||||
|
||||
| Token | Value | Usage |
|
||||
|-------|-------|-------|
|
||||
| white-0 | `#ffffff` | Primary background |
|
||||
| white-50 | `#fefefe` | Slightly warm white |
|
||||
| white-75 | `#fcfcfc` | Near-white |
|
||||
| white-100 | `#fafafa` | Secondary background |
|
||||
| white-200 | `#f7f7f7` | Card background |
|
||||
| white-300 | `#f5f5f5` | Tertiary background |
|
||||
| white-400 | `#f0f0f0` | Separator zones |
|
||||
| white-500 | `#ebebeb` | Light border |
|
||||
| white-600 | `#e5e5e5` | Disabled background |
|
||||
| white-700 | `#e0e0e0` | Deep white-gray |
|
||||
| white-800 | `#d9d9d9` | Placeholder |
|
||||
| white-900 | `#d4d4d4` | Divider lines |
|
||||
| white-1000 | `#cccccc` | Deepest white |
|
||||
|
||||
#### Gold Scale (Platinum Business Accent)
|
||||
|
||||
| Token | Value | Usage |
|
||||
|-------|-------|-------|
|
||||
| gold-25 | `#FFFDF5` | Extremely light gold background |
|
||||
| gold-50 | `#FEF9E7` | Light gold background |
|
||||
| gold-75 | `#FCF3D0` | Pale gold highlight |
|
||||
| gold-100 | `#FAECB8` | Gold hover state |
|
||||
| gold-200 | `#F5DC8A` | Bright gold accent |
|
||||
| gold-300 | `#E8C860` | Gold hover |
|
||||
| gold-400 | `#D4AF37` | **Primary gold (core)** |
|
||||
| gold-500 | `#B8972E` | Gold text |
|
||||
| gold-600 | `#9A7E26` | Deep gold accent |
|
||||
| gold-700 | `#7C651E` | Dark gold border |
|
||||
| gold-800 | `#5E4C16` | Deep gold background |
|
||||
| gold-900 | `#40330F` | Very deep gold |
|
||||
| gold-1000 | `#221A08` | Black gold |
|
||||
|
||||
#### Blue Scale (Primary Action Color)
|
||||
|
||||
| Token | Value | Usage |
|
||||
|-------|-------|-------|
|
||||
| blue-25 | `#F0F7FF` | Extremely light blue background |
|
||||
| blue-50 | `#E0EFFF` | Info alert background |
|
||||
| blue-75 | `#C2DFFF` | Light blue highlight |
|
||||
| blue-100 | `#A3CFFF` | Disabled blue |
|
||||
| blue-200 | `#66AFFF` | Bright blue |
|
||||
| blue-300 | `#338FFF` | Blue hover |
|
||||
| blue-400 | `#0070F3` | **Primary blue (core)** |
|
||||
| blue-500 | `#005FCC` | Blue text |
|
||||
| blue-600 | `#004FA6` | Deep blue accent |
|
||||
| blue-700 | `#003F80` | Dark blue border |
|
||||
| blue-800 | `#002F5A` | Deep blue background |
|
||||
| blue-900 | `#001F3D` | Very deep blue |
|
||||
| blue-1000 | `#001026` | Black blue |
|
||||
|
||||
#### Gray Scale (Text & Neutral Colors)
|
||||
|
||||
| Token | Value | Usage |
|
||||
|-------|-------|-------|
|
||||
| gray-0 | `#ffffff` | White |
|
||||
| gray-50 | `#fafafa` | Extremely light gray |
|
||||
| gray-75 | `#f5f5f5` | Light gray background |
|
||||
| gray-100 | `#ededed` | Light divider |
|
||||
| gray-200 | `#d4d4d4` | Light border |
|
||||
| gray-300 | `#a3a3a3` | Quaternary text |
|
||||
| gray-400 | `#737373` | Tertiary text |
|
||||
| gray-500 | `#525252` | Secondary text |
|
||||
| gray-600 | `#404040` | Dark gray |
|
||||
| gray-700 | `#2e2e2e` | Dark background |
|
||||
| gray-800 | `#1f1f1f` | Deep background |
|
||||
| gray-900 | `#141414` | Very deep background |
|
||||
| gray-1000 | `#0a0a0a` | **Primary text (core)** |
|
||||
|
||||
#### Opacity Values
|
||||
|
||||
##### Opacity Black
|
||||
|
||||
| Opacity | Value | Usage |
|
||||
|---------|-------|-------|
|
||||
| 0% | `#0a0a0a00` | Fully transparent |
|
||||
| 2% | `#0a0a0a05` | Subtle overlay |
|
||||
| 4% | `#0a0a0a0a` | Secondary interactive background |
|
||||
| 8% | `#0a0a0a14` | Border / divider |
|
||||
| 15% | `#0a0a0a26` | Pressed state |
|
||||
| 20% | `#0a0a0a33` | Light overlay |
|
||||
| 25% | `#0a0a0a40` | Medium overlay |
|
||||
| 50% | `#0a0a0a80` | Semi-transparent |
|
||||
| 70% | `#0a0a0ab2` | Deep overlay |
|
||||
| 80% | `#0a0a0acc` | Hover state |
|
||||
| 90% | `#0a0a0ae5` | Tooltip |
|
||||
| 95% | `#0a0a0af2` | Modal |
|
||||
|
||||
##### Opacity White
|
||||
|
||||
| Opacity | Value | Usage |
|
||||
|---------|-------|-------|
|
||||
| 0% | `#ffffff00` | Fully transparent |
|
||||
| 2% | `#ffffff05` | Subtle overlay |
|
||||
| 4% | `#ffffff0a` | Secondary interactive background |
|
||||
| 8% | `#ffffff12` | Border / divider |
|
||||
| 15% | `#ffffff26` | Pressed state |
|
||||
| 20% | `#ffffff33` | Light overlay |
|
||||
| 25% | `#ffffff40` | Medium overlay |
|
||||
| 50% | `#ffffff80` | Semi-transparent |
|
||||
| 70% | `#ffffffb2` | Deep overlay |
|
||||
| 80% | `#ffffffcc` | Hover state |
|
||||
| 90% | `#ffffffe5` | Tooltip |
|
||||
| 95% | `#fffffff2` | Modal |
|
||||
|
||||
---
|
||||
|
||||
## Color Palette Rules (MANDATORY)
|
||||
|
||||
### Strict Palette Adherence
|
||||
|
||||
**Use ONLY the provided color palette. Do NOT create or modify colors.**
|
||||
|
||||
- All colors must come from the user-provided palette
|
||||
- Do NOT use colors outside the palette
|
||||
- Do NOT modify palette colors (brightness, saturation, mixing)
|
||||
- **Only exception**: Add transparency using the `transparency` property (0-100)
|
||||
|
||||
```javascript
|
||||
// Correct: Using palette colors
|
||||
slide.addShape(pres.shapes.RECTANGLE, { fill: { color: theme.primary } });
|
||||
slide.addText("Title", { color: theme.accent });
|
||||
|
||||
// Wrong: Colors outside palette
|
||||
slide.addShape(pres.shapes.RECTANGLE, { fill: { color: "1a1a2e" } });
|
||||
```
|
||||
|
||||
### No Gradients
|
||||
|
||||
**Gradients are prohibited. Use solid colors only.**
|
||||
|
||||
### No Animations
|
||||
|
||||
**Animations and transitions are prohibited.** All slides must be static.
|
||||
|
||||
---
|
||||
|
||||
## Font Reference
|
||||
|
||||
### Recommended Fonts
|
||||
|
||||
| Language | Default Font | Alternatives |
|
||||
|----------|-------------|--------------|
|
||||
| **Chinese** | Microsoft YaHei | — |
|
||||
| **English** | Arial | Georgia, Calibri, Cambria, Trebuchet MS |
|
||||
|
||||
- For mixed Chinese-English content: use Microsoft YaHei for Chinese, the chosen font for English
|
||||
- Prefer system fonts for cross-platform compatibility
|
||||
- Titles and body text can use different font pairings (e.g. Georgia + Calibri)
|
||||
|
||||
### Recommended Font Pairings
|
||||
|
||||
| Header Font | Body Font |
|
||||
|-------------|-----------|
|
||||
| Georgia | Calibri |
|
||||
| Arial Black | Arial |
|
||||
| Calibri | Calibri Light |
|
||||
| Cambria | Calibri |
|
||||
| Trebuchet MS | Calibri |
|
||||
| Impact | Arial |
|
||||
| Palatino | Garamond |
|
||||
| Consolas | Calibri |
|
||||
|
||||
**Choose an interesting font pairing** — don't default to Arial for everything. Pick a header font with personality and pair it with a clean body font.
|
||||
|
||||
### No Bold for Body Text
|
||||
|
||||
**Plain body text and caption/legend text must NOT use bold.**
|
||||
|
||||
- Body paragraphs, descriptions → normal weight
|
||||
- Captions, legends, footnotes → normal weight
|
||||
- Reserve bold for titles and headings only
|
||||
|
||||
```javascript
|
||||
// Correct
|
||||
slide.addText("Main Title", { bold: true, fontSize: 36, fontFace: "Arial" });
|
||||
slide.addText("Body text here.", { bold: false, fontSize: 14, fontFace: "Arial" });
|
||||
|
||||
// Wrong
|
||||
slide.addText("Body text here.", { bold: true, fontSize: 14 });
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Style Recipes
|
||||
|
||||
The same design can be rendered in 4 distinct visual styles by adjusting corner radius (`rectRadius`) and spacing. Choose the style recipe that fits the presentation tone.
|
||||
|
||||
> **Unit note**: PptxGenJS uses inches. Slide dimensions are 10" x 5.625" (LAYOUT_16x9).
|
||||
|
||||
### Style Overview
|
||||
|
||||
| Style | Corner Radius | Spacing | Best For |
|
||||
|-------|--------------|---------|----------|
|
||||
| **Sharp & Compact** | 0 ~ 0.05" | Tight | Data-dense, tables, professional reports |
|
||||
| **Soft & Balanced** | 0.08" ~ 0.12" | Moderate | Corporate, business presentations, general use |
|
||||
| **Rounded & Spacious** | 0.15" ~ 0.25" | Relaxed | Product intros, marketing, creative showcases |
|
||||
| **Pill & Airy** | 0.3" ~ 0.5" | Open | Brand showcases, launch events, premium presentations |
|
||||
|
||||
### Sharp & Compact
|
||||
|
||||
**Visual character**: Geometric, high information density, formal and serious.
|
||||
|
||||
| Category | Value (inches) | Notes |
|
||||
|----------|---------------|-------|
|
||||
| Corner radius — small | 0" | Full right angle |
|
||||
| Corner radius — medium | 0.03" | Micro-rounded |
|
||||
| Corner radius — large | 0.05" | Slight rounding |
|
||||
| Element padding | 0.1" ~ 0.15" | Compact |
|
||||
| Element gap | 0.1" ~ 0.2" | Compact |
|
||||
| Page margin | 0.3" | Narrow |
|
||||
| Block gap | 0.25" ~ 0.35" | Compact |
|
||||
|
||||
### Soft & Balanced
|
||||
|
||||
**Visual character**: Moderate rounding, comfortable whitespace, professional yet approachable.
|
||||
|
||||
| Category | Value (inches) | Notes |
|
||||
|----------|---------------|-------|
|
||||
| Corner radius — small | 0.05" | Slight rounding |
|
||||
| Corner radius — medium | 0.08" | Medium rounding |
|
||||
| Corner radius — large | 0.12" | Larger rounding |
|
||||
| Element padding | 0.15" ~ 0.2" | Moderate |
|
||||
| Element gap | 0.15" ~ 0.25" | Moderate |
|
||||
| Page margin | 0.4" | Standard |
|
||||
| Block gap | 0.35" ~ 0.5" | Moderate |
|
||||
|
||||
### Rounded & Spacious
|
||||
|
||||
**Visual character**: Large corners, generous whitespace, friendly and modern.
|
||||
|
||||
| Category | Value (inches) | Notes |
|
||||
|----------|---------------|-------|
|
||||
| Corner radius — small | 0.1" | Medium rounding |
|
||||
| Corner radius — medium | 0.15" | Large rounding |
|
||||
| Corner radius — large | 0.25" | Very large rounding |
|
||||
| Element padding | 0.2" ~ 0.3" | Relaxed |
|
||||
| Element gap | 0.25" ~ 0.4" | Relaxed |
|
||||
| Page margin | 0.5" | Wide |
|
||||
| Block gap | 0.5" ~ 0.7" | Relaxed |
|
||||
|
||||
### Pill & Airy
|
||||
|
||||
**Visual character**: Full pill-shaped corners, abundant whitespace, light and open feel, strong brand presence.
|
||||
|
||||
| Category | Value (inches) | Notes |
|
||||
|----------|---------------|-------|
|
||||
| Corner radius — small | 0.2" | Large rounding |
|
||||
| Corner radius — medium | 0.3" | Pill shape |
|
||||
| Corner radius — large | 0.5" | Full pill |
|
||||
| Element padding | 0.25" ~ 0.4" | Open |
|
||||
| Element gap | 0.3" ~ 0.5" | Open |
|
||||
| Page margin | 0.6" | Wide |
|
||||
| Block gap | 0.6" ~ 0.9" | Open |
|
||||
|
||||
### Component Style Mapping
|
||||
|
||||
| Component | Sharp | Soft | Rounded | Pill |
|
||||
|-----------|-------|------|---------|------|
|
||||
| **Button / Tag** | rectRadius: 0 | rectRadius: 0.05 | rectRadius: 0.1 | rectRadius: 0.2 |
|
||||
| **Card / Container** | rectRadius: 0.03 | rectRadius: 0.1 | rectRadius: 0.2 | rectRadius: 0.3 |
|
||||
| **Image Container** | rectRadius: 0 | rectRadius: 0.08 | rectRadius: 0.15 | rectRadius: 0.25 |
|
||||
| **Input Field** | rectRadius: 0 | rectRadius: 0.05 | rectRadius: 0.1 | rectRadius: 0.2 |
|
||||
| **Badge** | rectRadius: 0.02 | rectRadius: 0.05 | rectRadius: 0.08 | rectRadius: 0.15 |
|
||||
| **Avatar Frame** | rectRadius: 0 | rectRadius: 0.1 | rectRadius: 0.2 | rectRadius: 0.5 (circle) |
|
||||
|
||||
#### PptxGenJS Corner Radius Examples
|
||||
|
||||
```javascript
|
||||
// Sharp style card
|
||||
slide.addShape("rect", {
|
||||
x: 0.5, y: 1, w: 4, h: 2.5,
|
||||
fill: { color: "F5F5F5" },
|
||||
rectRadius: 0.03
|
||||
});
|
||||
|
||||
// Rounded style card
|
||||
slide.addShape("rect", {
|
||||
x: 0.5, y: 1, w: 4, h: 2.5,
|
||||
fill: { color: "F5F5F5" },
|
||||
rectRadius: 0.2
|
||||
});
|
||||
|
||||
// Pill style button (height 0.4", rectRadius 0.2" = perfect pill)
|
||||
slide.addShape("rect", {
|
||||
x: 3, y: 4, w: 2, h: 0.4,
|
||||
fill: { color: "4A90D9" },
|
||||
rectRadius: 0.2
|
||||
});
|
||||
```
|
||||
|
||||
### Mixing Rules
|
||||
|
||||
#### 1. Outer container corner >= inner element corner
|
||||
|
||||
```javascript
|
||||
// Correct: outer > inner
|
||||
card: rectRadius: 0.2
|
||||
button: rectRadius: 0.1
|
||||
|
||||
// Wrong: inner > outer → visual overflow effect
|
||||
card: rectRadius: 0.1
|
||||
button: rectRadius: 0.2
|
||||
```
|
||||
|
||||
#### 2. Information density drives spacing
|
||||
|
||||
| Zone Type | Recommended Style |
|
||||
|-----------|------------------|
|
||||
| Data display zone | Sharp / Soft (compact spacing) |
|
||||
| Content browsing zone | Rounded / Pill (relaxed spacing) |
|
||||
| Title zone | Soft / Rounded (moderate spacing) |
|
||||
|
||||
#### 3. Corner radius vs element height
|
||||
|
||||
| Element Height | Sharp | Soft | Rounded | Pill |
|
||||
|---------------|-------|------|---------|------|
|
||||
| Small (< 0.3") | 0" | 0.03" | 0.08" | height/2 |
|
||||
| Medium (0.3" ~ 0.6") | 0.02" | 0.05" | 0.12" | height/2 |
|
||||
| Large (0.6" ~ 1.2") | 0.03" | 0.08" | 0.2" | 0.3" |
|
||||
| Extra large (> 1.2") | 0.05" | 0.12" | 0.25" | 0.4" |
|
||||
|
||||
> **Pill tip**: For a perfect pill shape, set `rectRadius = element height / 2`
|
||||
|
||||
### Typography Scale (PPT)
|
||||
|
||||
| Usage | Size (pt) | Notes |
|
||||
|-------|-----------|-------|
|
||||
| Annotations / Sources | 10 ~ 12 | Minimum readable size |
|
||||
| Body / Description | 14 ~ 16 | Standard body |
|
||||
| Subtitle | 18 ~ 22 | Secondary heading |
|
||||
| Title | 28 ~ 36 | Page title |
|
||||
| Large Title | 44 ~ 60 | Cover / section title |
|
||||
| Data Callout | 60 ~ 96 | Key number display |
|
||||
|
||||
### Spacing Scale (PPT)
|
||||
|
||||
Based on 10" x 5.625" slide dimensions:
|
||||
|
||||
| Usage | Recommended (inches) |
|
||||
|-------|---------------------|
|
||||
| Icon-to-text gap | 0.08" ~ 0.15" |
|
||||
| List item spacing | 0.15" ~ 0.25" |
|
||||
| Card inner padding | 0.2" ~ 0.4" |
|
||||
| Element group gap | 0.3" ~ 0.5" |
|
||||
| Page safe margin | 0.4" ~ 0.6" |
|
||||
| Major block gap | 0.5" ~ 0.8" |
|
||||
|
||||
### Quick Selection Guide
|
||||
|
||||
| Presentation Type | Recommended Style | Reason |
|
||||
|------------------|------------------|--------|
|
||||
| Finance / Data reports | Sharp & Compact | High density, serious and precise |
|
||||
| Corporate / Business | Soft & Balanced | Balances professionalism and approachability |
|
||||
| Product intro / Marketing | Rounded & Spacious | Modern feel, friendly |
|
||||
| Launch events / Brand | Pill & Airy | Premium feel, visual impact |
|
||||
| Training / Education | Soft / Rounded | Clear, readable, friendly |
|
||||
| Tech sharing | Sharp / Soft | Professional, information-dense |
|
||||
162
pptx-generator/references/editing.md
Normal file
162
pptx-generator/references/editing.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# Editing Existing Presentations
|
||||
|
||||
## Template-Based Workflow
|
||||
|
||||
When using an existing presentation as a template:
|
||||
|
||||
1. **Copy and analyze**:
|
||||
```bash
|
||||
cp /path/to/user-provided.pptx template.pptx
|
||||
python -m markitdown template.pptx > template.md
|
||||
```
|
||||
Review `template.md` to see placeholder text and slide structure.
|
||||
|
||||
2. **Plan slide mapping**: For each content section, choose a template slide.
|
||||
|
||||
**USE VARIED LAYOUTS** — monotonous presentations are a common failure mode. Don't default to basic title + bullet slides. Actively seek out:
|
||||
- Multi-column layouts (2-column, 3-column)
|
||||
- Image + text combinations
|
||||
- Full-bleed images with text overlay
|
||||
- Quote or callout slides
|
||||
- Section dividers
|
||||
- Stat/number callouts
|
||||
- Icon grids or icon + text rows
|
||||
|
||||
**Avoid:** Repeating the same text-heavy layout for every slide.
|
||||
|
||||
Match content type to layout style (e.g., key points -> bullet slide, team info -> multi-column, testimonials -> quote slide).
|
||||
|
||||
3. **Unpack**: Extract the PPTX into an editable XML tree using Python's `zipfile` module. Pretty-print the XML for readability.
|
||||
|
||||
4. **Build presentation** (do this yourself, not with subagents):
|
||||
- Delete unwanted slides (remove from `<p:sldIdLst>`)
|
||||
- Duplicate slides you want to reuse (copy slide XML, relationships, and update `Content_Types.xml` and `presentation.xml`)
|
||||
- Reorder slides in `<p:sldIdLst>`
|
||||
- **Complete all structural changes before step 5**
|
||||
|
||||
5. **Edit content**: Update text in each `slide{N}.xml`.
|
||||
**Use subagents here if available** — slides are separate XML files, so subagents can edit in parallel.
|
||||
|
||||
6. **Clean**: Remove orphaned files — slides not in `<p:sldIdLst>`, unreferenced media, orphaned rels.
|
||||
|
||||
7. **Pack**: Repack the XML tree into a PPTX file. Validate, repair, condense XML, re-encode smart quotes.
|
||||
|
||||
Always write to `/tmp/` first, then copy to the final path. Python's `zipfile` module uses `seek` internally, which fails on some volume mounts (e.g. Docker bind mounts). Writing to a local temp path avoids this.
|
||||
|
||||
## Output Structure
|
||||
|
||||
Copy the user-provided file to `template.pptx` in cwd. This preserves the original and gives a predictable name for all downstream operations.
|
||||
|
||||
```bash
|
||||
cp /path/to/user-provided.pptx template.pptx
|
||||
```
|
||||
|
||||
```text
|
||||
./
|
||||
├── template.pptx # Copy of user-provided file (never modified)
|
||||
├── template.md # markitdown extraction
|
||||
├── unpacked/ # Editable XML tree
|
||||
└── edited.pptx # Final repacked deck
|
||||
```
|
||||
|
||||
Minimum expected deliverable: `edited.pptx`.
|
||||
|
||||
## Slide Operations
|
||||
|
||||
Slide order is in `ppt/presentation.xml` -> `<p:sldIdLst>`.
|
||||
|
||||
**Reorder**: Rearrange `<p:sldId>` elements.
|
||||
|
||||
**Delete**: Remove `<p:sldId>`, then clean orphaned files.
|
||||
|
||||
**Add**: Copy the source slide's XML file, its `.rels` file, and update `Content_Types.xml` and `presentation.xml`. Never manually copy slide files without updating all references — this causes broken notes references and missing relationship IDs.
|
||||
|
||||
## Editing Content
|
||||
|
||||
**Subagents:** If available, use them here (after completing step 4). Each slide is a separate XML file, so subagents can edit in parallel. In your prompt to subagents, include:
|
||||
- The slide file path(s) to edit
|
||||
- **"Use the Edit tool for all changes"**
|
||||
- The formatting rules and common pitfalls below
|
||||
|
||||
For each slide:
|
||||
1. Read the slide's XML
|
||||
2. Identify ALL placeholder content — text, images, charts, icons, captions
|
||||
3. Replace each placeholder with final content
|
||||
|
||||
**Use the Edit tool, not sed or Python scripts.** The Edit tool forces specificity about what to replace and where, yielding better reliability.
|
||||
|
||||
## Formatting Rules
|
||||
|
||||
- **Bold all headers, subheadings, and inline labels**: Use `b="1"` on `<a:rPr>`. This includes:
|
||||
- Slide titles
|
||||
- Section headers within a slide
|
||||
- Inline labels like (e.g.: "Status:", "Description:") at the start of a line
|
||||
- **Never use unicode bullets**: Use proper list formatting with `<a:buChar>` or `<a:buAutoNum>`
|
||||
- **Bullet consistency**: Let bullets inherit from the layout. Only specify `<a:buChar>` or `<a:buNone>`.
|
||||
|
||||
## Common Pitfalls — Template Editing
|
||||
|
||||
### Template Adaptation
|
||||
|
||||
When source content has fewer items than the template:
|
||||
- **Remove excess elements entirely** (images, shapes, text boxes), don't just clear text
|
||||
- Check for orphaned visuals after clearing text content
|
||||
- Run content QA with `markitdown` to catch mismatched counts
|
||||
|
||||
When replacing text with different length content:
|
||||
- **Shorter replacements**: Usually safe
|
||||
- **Longer replacements**: May overflow or wrap unexpectedly
|
||||
- Verify with `markitdown` after text changes
|
||||
- Consider truncating or splitting content to fit the template's design constraints
|
||||
|
||||
**Template slots != Source items**: If template has 4 team members but source has 3 users, delete the 4th member's entire group (image + text boxes), not just the text.
|
||||
|
||||
### Multi-Item Content
|
||||
|
||||
If source has multiple items (numbered lists, multiple sections), create separate `<a:p>` elements for each — **never concatenate into one string**.
|
||||
|
||||
**WRONG** — all items in one paragraph:
|
||||
```xml
|
||||
<a:p>
|
||||
<a:r><a:rPr .../><a:t>Step 1: Do the first thing. Step 2: Do the second thing.</a:t></a:r>
|
||||
</a:p>
|
||||
```
|
||||
|
||||
**CORRECT** — separate paragraphs with bold headers:
|
||||
```xml
|
||||
<a:p>
|
||||
<a:pPr algn="l"><a:lnSpc><a:spcPts val="3919"/></a:lnSpc></a:pPr>
|
||||
<a:r><a:rPr lang="en-US" sz="2799" b="1" .../><a:t>Step 1</a:t></a:r>
|
||||
</a:p>
|
||||
<a:p>
|
||||
<a:pPr algn="l"><a:lnSpc><a:spcPts val="3919"/></a:lnSpc></a:pPr>
|
||||
<a:r><a:rPr lang="en-US" sz="2799" .../><a:t>Do the first thing.</a:t></a:r>
|
||||
</a:p>
|
||||
<a:p>
|
||||
<a:pPr algn="l"><a:lnSpc><a:spcPts val="3919"/></a:lnSpc></a:pPr>
|
||||
<a:r><a:rPr lang="en-US" sz="2799" b="1" .../><a:t>Step 2</a:t></a:r>
|
||||
</a:p>
|
||||
<!-- continue pattern -->
|
||||
```
|
||||
|
||||
Copy `<a:pPr>` from the original paragraph to preserve line spacing. Use `b="1"` on headers.
|
||||
|
||||
### Smart Quotes
|
||||
|
||||
The Edit tool converts smart quotes to ASCII. **When adding new text with quotes, use XML entities:**
|
||||
|
||||
```xml
|
||||
<a:t>the “Agreement”</a:t>
|
||||
```
|
||||
|
||||
| Character | Name | Unicode | XML Entity |
|
||||
|-----------|------|---------|------------|
|
||||
| \u201c | Left double quote | U+201C | `“` |
|
||||
| \u201d | Right double quote | U+201D | `”` |
|
||||
| \u2018 | Left single quote | U+2018 | `‘` |
|
||||
| \u2019 | Right single quote | U+2019 | `’` |
|
||||
|
||||
### Other
|
||||
|
||||
- **Whitespace**: Use `xml:space="preserve"` on `<a:t>` with leading/trailing spaces
|
||||
- **XML parsing**: Use `defusedxml.minidom`, not `xml.etree.ElementTree` (corrupts namespaces)
|
||||
112
pptx-generator/references/pitfalls.md
Normal file
112
pptx-generator/references/pitfalls.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# QA Process & Common Pitfalls
|
||||
|
||||
## QA Process
|
||||
|
||||
**Assume there are problems. Your job is to find them.**
|
||||
|
||||
Your first render is almost never correct. Approach QA as a bug hunt, not a confirmation step. If you found zero issues on first inspection, you weren't looking hard enough.
|
||||
|
||||
### Content QA
|
||||
|
||||
```bash
|
||||
python -m markitdown output.pptx
|
||||
```
|
||||
|
||||
Check for missing content, typos, wrong order.
|
||||
|
||||
**Check for leftover placeholder text:**
|
||||
|
||||
```bash
|
||||
python -m markitdown output.pptx | grep -iE "xxxx|lorem|ipsum|placeholder|this.*(page|slide).*layout"
|
||||
```
|
||||
|
||||
If grep returns results, fix them before declaring success.
|
||||
|
||||
### Verification Loop
|
||||
|
||||
1. Generate slides -> Extract text with `python -m markitdown output.pptx` -> Review content
|
||||
2. **List issues found** (if none found, look again more critically)
|
||||
3. Fix issues
|
||||
4. **Re-verify affected slides** — one fix often creates another problem
|
||||
5. Repeat until a full pass reveals no new issues
|
||||
|
||||
**Do not declare success until you've completed at least one fix-and-verify cycle.**
|
||||
|
||||
### Per-Slide QA (for from-scratch creation)
|
||||
|
||||
```bash
|
||||
python -m markitdown slide-XX-preview.pptx
|
||||
```
|
||||
|
||||
Check for missing content, placeholder text, missing page number badge.
|
||||
|
||||
---
|
||||
|
||||
## Common Mistakes to Avoid
|
||||
|
||||
- **Don't repeat the same layout** — vary columns, cards, and callouts across slides
|
||||
- **Don't center body text** — left-align paragraphs and lists; center only titles
|
||||
- **Don't skimp on size contrast** — titles need 36pt+ to stand out from 14-16pt body
|
||||
- **Don't default to blue** — pick colors that reflect the specific topic
|
||||
- **Don't mix spacing randomly** — choose 0.3" or 0.5" gaps and use consistently
|
||||
- **Don't style one slide and leave the rest plain** — commit fully or keep it simple throughout
|
||||
- **Don't create text-only slides** — add images, icons, charts, or visual elements; avoid plain title + bullets
|
||||
- **Don't forget text box padding** — when aligning lines or shapes with text edges, set `margin: 0` on the text box or offset the shape to account for padding
|
||||
- **Don't use low-contrast elements** — icons AND text need strong contrast against the background
|
||||
- **NEVER use accent lines under titles** — these are a hallmark of AI-generated slides; use whitespace or background color instead
|
||||
- **NEVER use "#" with hex colors** — causes file corruption in PptxGenJS
|
||||
- **NEVER encode opacity in hex strings** — use the `opacity` property instead
|
||||
- **NEVER use async/await in createSlide()** — compile.js won't await
|
||||
- **NEVER reuse option objects across PptxGenJS calls** — PptxGenJS mutates objects in-place
|
||||
|
||||
---
|
||||
|
||||
## Critical Pitfalls — PptxGenJS
|
||||
|
||||
### NEVER use async/await in createSlide()
|
||||
|
||||
```javascript
|
||||
// WRONG - compile.js won't await
|
||||
async function createSlide(pres, theme) { ... }
|
||||
|
||||
// CORRECT
|
||||
function createSlide(pres, theme) { ... }
|
||||
```
|
||||
|
||||
### NEVER use "#" with hex colors
|
||||
|
||||
```javascript
|
||||
color: "FF0000" // CORRECT
|
||||
color: "#FF0000" // CORRUPTS FILE
|
||||
```
|
||||
|
||||
### NEVER encode opacity in hex strings
|
||||
|
||||
```javascript
|
||||
shadow: { color: "00000020" } // CORRUPTS FILE
|
||||
shadow: { color: "000000", opacity: 0.12 } // CORRECT
|
||||
```
|
||||
|
||||
### Prevent text wrapping in titles
|
||||
|
||||
```javascript
|
||||
// Use fit:'shrink' for long titles
|
||||
slide.addText("Long Title Here", {
|
||||
x: 0.5, y: 2, w: 9, h: 1,
|
||||
fontSize: 48, fit: "shrink"
|
||||
});
|
||||
```
|
||||
|
||||
### NEVER reuse option objects across calls
|
||||
|
||||
```javascript
|
||||
// WRONG
|
||||
const shadow = { type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.15 };
|
||||
slide.addShape(pres.shapes.RECTANGLE, { shadow, ... });
|
||||
slide.addShape(pres.shapes.RECTANGLE, { shadow, ... });
|
||||
|
||||
// CORRECT - factory function
|
||||
const makeShadow = () => ({ type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.15 });
|
||||
slide.addShape(pres.shapes.RECTANGLE, { shadow: makeShadow(), ... });
|
||||
slide.addShape(pres.shapes.RECTANGLE, { shadow: makeShadow(), ... });
|
||||
```
|
||||
420
pptx-generator/references/pptxgenjs.md
Normal file
420
pptx-generator/references/pptxgenjs.md
Normal file
@@ -0,0 +1,420 @@
|
||||
# PptxGenJS Tutorial
|
||||
|
||||
## Setup & Basic Structure
|
||||
|
||||
```javascript
|
||||
const pptxgen = require("pptxgenjs");
|
||||
|
||||
let pres = new pptxgen();
|
||||
pres.layout = 'LAYOUT_16x9'; // or 'LAYOUT_16x10', 'LAYOUT_4x3', 'LAYOUT_WIDE'
|
||||
pres.author = 'Your Name';
|
||||
pres.title = 'Presentation Title';
|
||||
|
||||
let slide = pres.addSlide();
|
||||
slide.addText("Hello World!", { x: 0.5, y: 0.5, fontSize: 36, color: "363636" });
|
||||
|
||||
pres.writeFile({ fileName: "Presentation.pptx" });
|
||||
```
|
||||
|
||||
## Layout Dimensions
|
||||
|
||||
Slide dimensions (coordinates in inches):
|
||||
- `LAYOUT_16x9`: 10" x 5.625" (default)
|
||||
- `LAYOUT_16x10`: 10" x 6.25"
|
||||
- `LAYOUT_4x3`: 10" x 7.5"
|
||||
- `LAYOUT_WIDE`: 13.3" x 7.5"
|
||||
|
||||
---
|
||||
|
||||
## Text & Formatting
|
||||
|
||||
```javascript
|
||||
// Basic text
|
||||
slide.addText("Simple Text", {
|
||||
x: 1, y: 1, w: 8, h: 2, fontSize: 24, fontFace: "Arial",
|
||||
color: "363636", bold: true, align: "center", valign: "middle"
|
||||
});
|
||||
|
||||
// Character spacing (use charSpacing, not letterSpacing which is silently ignored)
|
||||
slide.addText("SPACED TEXT", { x: 1, y: 1, w: 8, h: 1, charSpacing: 6 });
|
||||
|
||||
// Rich text arrays
|
||||
slide.addText([
|
||||
{ text: "Bold ", options: { bold: true } },
|
||||
{ text: "Italic ", options: { italic: true } }
|
||||
], { x: 1, y: 3, w: 8, h: 1 });
|
||||
|
||||
// Multi-line text (requires breakLine: true)
|
||||
slide.addText([
|
||||
{ text: "Line 1", options: { breakLine: true } },
|
||||
{ text: "Line 2", options: { breakLine: true } },
|
||||
{ text: "Line 3" } // Last item doesn't need breakLine
|
||||
], { x: 0.5, y: 0.5, w: 8, h: 2 });
|
||||
|
||||
// Text box margin (internal padding)
|
||||
slide.addText("Title", {
|
||||
x: 0.5, y: 0.3, w: 9, h: 0.6,
|
||||
margin: 0 // Use 0 when aligning text with other elements like shapes or icons
|
||||
});
|
||||
```
|
||||
|
||||
**Tip:** Text boxes have internal margin by default. Set `margin: 0` when you need text to align precisely with shapes, lines, or icons at the same x-position.
|
||||
|
||||
---
|
||||
|
||||
## Lists & Bullets
|
||||
|
||||
```javascript
|
||||
// CORRECT: Multiple bullets
|
||||
slide.addText([
|
||||
{ text: "First item", options: { bullet: true, breakLine: true } },
|
||||
{ text: "Second item", options: { bullet: true, breakLine: true } },
|
||||
{ text: "Third item", options: { bullet: true } }
|
||||
], { x: 0.5, y: 0.5, w: 8, h: 3 });
|
||||
|
||||
// WRONG: Never use unicode bullets
|
||||
slide.addText("* First item", { ... }); // Creates double bullets
|
||||
|
||||
// Sub-items and numbered lists
|
||||
{ text: "Sub-item", options: { bullet: true, indentLevel: 1 } }
|
||||
{ text: "First", options: { bullet: { type: "number" }, breakLine: true } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Shapes
|
||||
|
||||
```javascript
|
||||
slide.addShape(pres.shapes.RECTANGLE, {
|
||||
x: 0.5, y: 0.8, w: 1.5, h: 3.0,
|
||||
fill: { color: "FF0000" }, line: { color: "000000", width: 2 }
|
||||
});
|
||||
|
||||
slide.addShape(pres.shapes.OVAL, { x: 4, y: 1, w: 2, h: 2, fill: { color: "0000FF" } });
|
||||
|
||||
slide.addShape(pres.shapes.LINE, {
|
||||
x: 1, y: 3, w: 5, h: 0, line: { color: "FF0000", width: 3, dashType: "dash" }
|
||||
});
|
||||
|
||||
// With transparency
|
||||
slide.addShape(pres.shapes.RECTANGLE, {
|
||||
x: 1, y: 1, w: 3, h: 2,
|
||||
fill: { color: "0088CC", transparency: 50 }
|
||||
});
|
||||
|
||||
// Rounded rectangle (rectRadius only works with ROUNDED_RECTANGLE, not RECTANGLE)
|
||||
// Don't pair with rectangular accent overlays -- they won't cover rounded corners. Use RECTANGLE instead.
|
||||
slide.addShape(pres.shapes.ROUNDED_RECTANGLE, {
|
||||
x: 1, y: 1, w: 3, h: 2,
|
||||
fill: { color: "FFFFFF" }, rectRadius: 0.1
|
||||
});
|
||||
|
||||
// With shadow
|
||||
slide.addShape(pres.shapes.RECTANGLE, {
|
||||
x: 1, y: 1, w: 3, h: 2,
|
||||
fill: { color: "FFFFFF" },
|
||||
shadow: { type: "outer", color: "000000", blur: 6, offset: 2, angle: 135, opacity: 0.15 }
|
||||
});
|
||||
```
|
||||
|
||||
Shadow options:
|
||||
|
||||
| Property | Type | Range | Notes |
|
||||
|----------|------|-------|-------|
|
||||
| `type` | string | `"outer"`, `"inner"` | |
|
||||
| `color` | string | 6-char hex (e.g. `"000000"`) | No `#` prefix, no 8-char hex -- see Common Pitfalls |
|
||||
| `blur` | number | 0-100 pt | |
|
||||
| `offset` | number | 0-200 pt | **Must be non-negative** -- negative values corrupt the file |
|
||||
| `angle` | number | 0-359 degrees | Direction the shadow falls (135 = bottom-right, 270 = upward) |
|
||||
| `opacity` | number | 0.0-1.0 | Use this for transparency, never encode in color string |
|
||||
|
||||
To cast a shadow upward (e.g. on a footer bar), use `angle: 270` with a positive offset -- do **not** use a negative offset.
|
||||
|
||||
**Note**: Gradient fills are not natively supported. Use a gradient image as a background instead.
|
||||
|
||||
---
|
||||
|
||||
## Images
|
||||
|
||||
### Image Sources
|
||||
|
||||
```javascript
|
||||
// From file path
|
||||
slide.addImage({ path: "images/chart.png", x: 1, y: 1, w: 5, h: 3 });
|
||||
|
||||
// From URL
|
||||
slide.addImage({ path: "https://example.com/image.jpg", x: 1, y: 1, w: 5, h: 3 });
|
||||
|
||||
// From base64 (faster, no file I/O)
|
||||
slide.addImage({ data: "image/png;base64,iVBORw0KGgo...", x: 1, y: 1, w: 5, h: 3 });
|
||||
```
|
||||
|
||||
### Image Options
|
||||
|
||||
```javascript
|
||||
slide.addImage({
|
||||
path: "image.png",
|
||||
x: 1, y: 1, w: 5, h: 3,
|
||||
rotate: 45, // 0-359 degrees
|
||||
rounding: true, // Circular crop
|
||||
transparency: 50, // 0-100
|
||||
flipH: true, // Horizontal flip
|
||||
flipV: false, // Vertical flip
|
||||
altText: "Description", // Accessibility
|
||||
hyperlink: { url: "https://example.com" }
|
||||
});
|
||||
```
|
||||
|
||||
### Image Sizing Modes
|
||||
|
||||
```javascript
|
||||
// Contain - fit inside, preserve ratio
|
||||
{ sizing: { type: 'contain', w: 4, h: 3 } }
|
||||
|
||||
// Cover - fill area, preserve ratio (may crop)
|
||||
{ sizing: { type: 'cover', w: 4, h: 3 } }
|
||||
|
||||
// Crop - cut specific portion
|
||||
{ sizing: { type: 'crop', x: 0.5, y: 0.5, w: 2, h: 2 } }
|
||||
```
|
||||
|
||||
### Calculate Dimensions (preserve aspect ratio)
|
||||
|
||||
```javascript
|
||||
const origWidth = 1978, origHeight = 923, maxHeight = 3.0;
|
||||
const calcWidth = maxHeight * (origWidth / origHeight);
|
||||
const centerX = (10 - calcWidth) / 2;
|
||||
|
||||
slide.addImage({ path: "image.png", x: centerX, y: 1.2, w: calcWidth, h: maxHeight });
|
||||
```
|
||||
|
||||
### Supported Formats
|
||||
|
||||
- **Standard**: PNG, JPG, GIF (animated GIFs work in Microsoft 365)
|
||||
- **SVG**: Works in modern PowerPoint/Microsoft 365
|
||||
|
||||
---
|
||||
|
||||
## Icons
|
||||
|
||||
Use react-icons to generate SVG icons, then rasterize to PNG for universal compatibility.
|
||||
|
||||
### Setup
|
||||
|
||||
```javascript
|
||||
const React = require("react");
|
||||
const ReactDOMServer = require("react-dom/server");
|
||||
const sharp = require("sharp");
|
||||
const { FaCheckCircle, FaChartLine } = require("react-icons/fa");
|
||||
|
||||
function renderIconSvg(IconComponent, color = "#000000", size = 256) {
|
||||
return ReactDOMServer.renderToStaticMarkup(
|
||||
React.createElement(IconComponent, { color, size: String(size) })
|
||||
);
|
||||
}
|
||||
|
||||
async function iconToBase64Png(IconComponent, color, size = 256) {
|
||||
const svg = renderIconSvg(IconComponent, color, size);
|
||||
const pngBuffer = await sharp(Buffer.from(svg)).png().toBuffer();
|
||||
return "image/png;base64," + pngBuffer.toString("base64");
|
||||
}
|
||||
```
|
||||
|
||||
### Add Icon to Slide
|
||||
|
||||
```javascript
|
||||
const iconData = await iconToBase64Png(FaCheckCircle, "#4472C4", 256);
|
||||
|
||||
slide.addImage({
|
||||
data: iconData,
|
||||
x: 1, y: 1, w: 0.5, h: 0.5 // Size in inches
|
||||
});
|
||||
```
|
||||
|
||||
**Note**: Use size 256 or higher for crisp icons. The size parameter controls the rasterization resolution, not the display size on the slide (which is set by `w` and `h` in inches).
|
||||
|
||||
### Icon Libraries
|
||||
|
||||
Install: `npm install -g react-icons react react-dom sharp`
|
||||
|
||||
Popular icon sets in react-icons:
|
||||
- `react-icons/fa` - Font Awesome
|
||||
- `react-icons/md` - Material Design
|
||||
- `react-icons/hi` - Heroicons
|
||||
- `react-icons/bi` - Bootstrap Icons
|
||||
|
||||
---
|
||||
|
||||
## Slide Backgrounds
|
||||
|
||||
```javascript
|
||||
// Solid color
|
||||
slide.background = { color: "F1F1F1" };
|
||||
|
||||
// Color with transparency
|
||||
slide.background = { color: "FF3399", transparency: 50 };
|
||||
|
||||
// Image from URL
|
||||
slide.background = { path: "https://example.com/bg.jpg" };
|
||||
|
||||
// Image from base64
|
||||
slide.background = { data: "image/png;base64,iVBORw0KGgo..." };
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tables
|
||||
|
||||
```javascript
|
||||
slide.addTable([
|
||||
["Header 1", "Header 2"],
|
||||
["Cell 1", "Cell 2"]
|
||||
], {
|
||||
x: 1, y: 1, w: 8, h: 2,
|
||||
border: { pt: 1, color: "999999" }, fill: { color: "F1F1F1" }
|
||||
});
|
||||
|
||||
// Advanced with merged cells
|
||||
let tableData = [
|
||||
[{ text: "Header", options: { fill: { color: "6699CC" }, color: "FFFFFF", bold: true } }, "Cell"],
|
||||
[{ text: "Merged", options: { colspan: 2 } }]
|
||||
];
|
||||
slide.addTable(tableData, { x: 1, y: 3.5, w: 8, colW: [4, 4] });
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Charts
|
||||
|
||||
```javascript
|
||||
// Bar chart
|
||||
slide.addChart(pres.charts.BAR, [{
|
||||
name: "Sales", labels: ["Q1", "Q2", "Q3", "Q4"], values: [4500, 5500, 6200, 7100]
|
||||
}], {
|
||||
x: 0.5, y: 0.6, w: 6, h: 3, barDir: 'col',
|
||||
showTitle: true, title: 'Quarterly Sales'
|
||||
});
|
||||
|
||||
// Line chart
|
||||
slide.addChart(pres.charts.LINE, [{
|
||||
name: "Temp", labels: ["Jan", "Feb", "Mar"], values: [32, 35, 42]
|
||||
}], { x: 0.5, y: 4, w: 6, h: 3, lineSize: 3, lineSmooth: true });
|
||||
|
||||
// Pie chart
|
||||
slide.addChart(pres.charts.PIE, [{
|
||||
name: "Share", labels: ["A", "B", "Other"], values: [35, 45, 20]
|
||||
}], { x: 7, y: 1, w: 5, h: 4, showPercent: true });
|
||||
```
|
||||
|
||||
### Better-Looking Charts
|
||||
|
||||
Default charts look dated. Apply these options for a modern, clean appearance:
|
||||
|
||||
```javascript
|
||||
slide.addChart(pres.charts.BAR, chartData, {
|
||||
x: 0.5, y: 1, w: 9, h: 4, barDir: "col",
|
||||
|
||||
// Custom colors (match your presentation palette)
|
||||
chartColors: ["0D9488", "14B8A6", "5EEAD4"],
|
||||
|
||||
// Clean background
|
||||
chartArea: { fill: { color: "FFFFFF" }, roundedCorners: true },
|
||||
|
||||
// Muted axis labels
|
||||
catAxisLabelColor: "64748B",
|
||||
valAxisLabelColor: "64748B",
|
||||
|
||||
// Subtle grid (value axis only)
|
||||
valGridLine: { color: "E2E8F0", size: 0.5 },
|
||||
catGridLine: { style: "none" },
|
||||
|
||||
// Data labels on bars
|
||||
showValue: true,
|
||||
dataLabelPosition: "outEnd",
|
||||
dataLabelColor: "1E293B",
|
||||
|
||||
// Hide legend for single series
|
||||
showLegend: false,
|
||||
});
|
||||
```
|
||||
|
||||
**Key styling options:**
|
||||
- `chartColors: [...]` - hex colors for series/segments
|
||||
- `chartArea: { fill, border, roundedCorners }` - chart background
|
||||
- `catGridLine/valGridLine: { color, style, size }` - grid lines (`style: "none"` to hide)
|
||||
- `lineSmooth: true` - curved lines (line charts)
|
||||
- `legendPos: "r"` - legend position: "b", "t", "l", "r", "tr"
|
||||
|
||||
---
|
||||
|
||||
## Slide Masters
|
||||
|
||||
```javascript
|
||||
pres.defineSlideMaster({
|
||||
title: 'TITLE_SLIDE', background: { color: '283A5E' },
|
||||
objects: [{
|
||||
placeholder: { options: { name: 'title', type: 'title', x: 1, y: 2, w: 8, h: 2 } }
|
||||
}]
|
||||
});
|
||||
|
||||
let titleSlide = pres.addSlide({ masterName: "TITLE_SLIDE" });
|
||||
titleSlide.addText("My Title", { placeholder: "title" });
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
These issues cause file corruption, visual bugs, or broken output. Avoid them.
|
||||
|
||||
1. **NEVER use "#" with hex colors** - causes file corruption
|
||||
```javascript
|
||||
color: "FF0000" // CORRECT
|
||||
color: "#FF0000" // WRONG
|
||||
```
|
||||
|
||||
2. **NEVER encode opacity in hex color strings** - 8-char colors (e.g., `"00000020"`) corrupt the file. Use the `opacity` property instead.
|
||||
```javascript
|
||||
shadow: { type: "outer", blur: 6, offset: 2, color: "00000020" } // CORRUPTS FILE
|
||||
shadow: { type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.12 } // CORRECT
|
||||
```
|
||||
|
||||
3. **Use `bullet: true`** - NEVER unicode symbols like "o" (creates double bullets)
|
||||
|
||||
4. **Use `breakLine: true`** between array items or text runs together
|
||||
|
||||
5. **Avoid `lineSpacing` with bullets** - causes excessive gaps; use `paraSpaceAfter` instead
|
||||
|
||||
6. **Each presentation needs fresh instance** - don't reuse `pptxgen()` objects
|
||||
|
||||
7. **NEVER reuse option objects across calls** - PptxGenJS mutates objects in-place (e.g. converting shadow values to EMU). Sharing one object between multiple calls corrupts the second shape.
|
||||
```javascript
|
||||
const shadow = { type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.15 };
|
||||
slide.addShape(pres.shapes.RECTANGLE, { shadow, ... }); // second call gets already-converted values
|
||||
slide.addShape(pres.shapes.RECTANGLE, { shadow, ... });
|
||||
|
||||
const makeShadow = () => ({ type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.15 });
|
||||
slide.addShape(pres.shapes.RECTANGLE, { shadow: makeShadow(), ... }); // fresh object each time
|
||||
slide.addShape(pres.shapes.RECTANGLE, { shadow: makeShadow(), ... });
|
||||
```
|
||||
|
||||
8. **Don't use `ROUNDED_RECTANGLE` with accent borders** - rectangular overlay bars won't cover rounded corners. Use `RECTANGLE` instead.
|
||||
```javascript
|
||||
// WRONG: Accent bar doesn't cover rounded corners
|
||||
slide.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 1, y: 1, w: 3, h: 1.5, fill: { color: "FFFFFF" } });
|
||||
slide.addShape(pres.shapes.RECTANGLE, { x: 1, y: 1, w: 0.08, h: 1.5, fill: { color: "0891B2" } });
|
||||
|
||||
// CORRECT: Use RECTANGLE for clean alignment
|
||||
slide.addShape(pres.shapes.RECTANGLE, { x: 1, y: 1, w: 3, h: 1.5, fill: { color: "FFFFFF" } });
|
||||
slide.addShape(pres.shapes.RECTANGLE, { x: 1, y: 1, w: 0.08, h: 1.5, fill: { color: "0891B2" } });
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
- **Shapes**: RECTANGLE, OVAL, LINE, ROUNDED_RECTANGLE
|
||||
- **Charts**: BAR, LINE, PIE, DOUGHNUT, SCATTER, BUBBLE, RADAR
|
||||
- **Layouts**: LAYOUT_16x9 (10"x5.625"), LAYOUT_16x10, LAYOUT_4x3, LAYOUT_WIDE
|
||||
- **Alignment**: "left", "center", "right"
|
||||
- **Chart data labels**: "outEnd", "inEnd", "center"
|
||||
413
pptx-generator/references/slide-types.md
Normal file
413
pptx-generator/references/slide-types.md
Normal file
@@ -0,0 +1,413 @@
|
||||
# Slide Page Types
|
||||
|
||||
Classify **every slide** as **exactly one** of these 5 types:
|
||||
|
||||
## 1. Cover Page
|
||||
|
||||
- **Use for**: Opening + tone setting
|
||||
- **Content**: Big title, subtitle/presenter, date/occasion, strong background/motif
|
||||
|
||||
### Layout Options
|
||||
|
||||
**Asymmetric Left-Right Layout**
|
||||
- Text concentrated on one side, image on the opposite
|
||||
- Best for: Corporate presentations, product launches, professional reports
|
||||
```
|
||||
| Title & Subtitle | Visual/Image |
|
||||
| Description | |
|
||||
```
|
||||
|
||||
**Center-Aligned Layout**
|
||||
- Content centered with background image
|
||||
- Best for: Inspirational talks, event presentations, creative pitches
|
||||
```
|
||||
| |
|
||||
| [Background Image] |
|
||||
| MAIN TITLE |
|
||||
| Subtitle |
|
||||
| |
|
||||
```
|
||||
|
||||
### Font Size Hierarchy
|
||||
|
||||
| Element | Recommended Size | Ratio to Base |
|
||||
|---------|-----------------|---------------|
|
||||
| Main Title | 72-120px | 3x-5x |
|
||||
| Subtitle | 28-40px | 1.5x-2x |
|
||||
| Supporting Text | 18-24px | 1x (base) |
|
||||
| Meta Info (date, name) | 14-18px | 0.7x-1x |
|
||||
|
||||
**Key Principles:**
|
||||
1. **Dramatic Contrast**: Main title should be at least 2-3x larger than subtitle
|
||||
2. **Visual Anchor**: The largest text becomes the focal point
|
||||
3. **Readable Hierarchy**: Viewers should instantly understand what's most important
|
||||
4. **Avoid Similarity**: Never let adjacent text elements be within 20% of each other's size
|
||||
|
||||
### Content Elements
|
||||
|
||||
1. **Main Title** — Always required, largest font
|
||||
2. **Subtitle** — When additional context is needed (clearly smaller than title)
|
||||
3. **Icons** — When they reinforce the theme
|
||||
4. **Date/Event Info** — When relevant (smallest text)
|
||||
5. **Company/Brand Logo** — When representing an organization
|
||||
6. **Presenter Name** — For keynotes (small, subtle)
|
||||
|
||||
### Design Decisions
|
||||
|
||||
Consider: Purpose (corporate/educational/creative), Audience, Tone, Content Volume, Visual Assets needed.
|
||||
|
||||
### Workflow
|
||||
|
||||
1. **Analyze**: Understand topic, audience, purpose
|
||||
2. **Choose Layout**: Select based on content
|
||||
3. **Write Slide**: Use PptxGenJS. Use shapes and SVG elements for visual interest.
|
||||
4. **Verify**: Generate preview as `slide-XX-preview.pptx`. Extract text with `python -m markitdown slide-XX-preview.pptx`, verify all content present and no placeholder text remains.
|
||||
|
||||
---
|
||||
|
||||
## 2. Table of Contents
|
||||
|
||||
- **Use for**: Navigation + expectation setting (3-5 sections)
|
||||
- **Content**: Section list (optional icons / page numbers)
|
||||
|
||||
### Layout Options
|
||||
|
||||
**Numbered Vertical List** — Best for 3-5 sections, straightforward presentations
|
||||
```
|
||||
| TABLE OF CONTENTS |
|
||||
| |
|
||||
| 01 Section Title One |
|
||||
| 02 Section Title Two |
|
||||
| 03 Section Title Three |
|
||||
```
|
||||
|
||||
**Two-Column Grid** — Best for 4-6 sections, content-rich presentations
|
||||
```
|
||||
| TABLE OF CONTENTS |
|
||||
| |
|
||||
| 01 Section One 02 Section Two |
|
||||
| Description Description |
|
||||
| 03 Section Three 04 Section Four |
|
||||
```
|
||||
|
||||
**Sidebar Navigation** — Best for 3-5 sections, modern/corporate
|
||||
```
|
||||
| ▌01 | Section Title One |
|
||||
| ▌02 | Section Title Two |
|
||||
| ▌03 | Section Title Three |
|
||||
```
|
||||
|
||||
**Card-Based** — Best for 3-4 sections, creative/modern
|
||||
```
|
||||
| TABLE OF CONTENTS |
|
||||
| ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ |
|
||||
| │ 01 │ │ 02 │ │ 03 │ │ 04 │ |
|
||||
| │Title│ │Title│ │Title│ │Title│ |
|
||||
| └─────┘ └─────┘ └─────┘ └─────┘ |
|
||||
```
|
||||
|
||||
### Font Size Hierarchy
|
||||
|
||||
| Element | Recommended Size | Ratio to Base |
|
||||
|---------|-----------------|---------------|
|
||||
| Page Title ("Table of Contents" / "Agenda") | 36-44px | 2.5x-3x |
|
||||
| Section Number | 28-36px | 2x-2.5x |
|
||||
| Section Title | 20-28px | 1.5x-2x |
|
||||
| Section Description | 14-16px | 1x (base) |
|
||||
|
||||
**Key Principles:**
|
||||
1. **Clear Numbering**: Section numbers should be visually prominent — bold, accent color, or larger size
|
||||
2. **Scannable Structure**: Viewer should scan all sections in 2-3 seconds
|
||||
3. **Consistent Spacing**: Equal vertical spacing between sections
|
||||
4. **Visual Markers**: Colored dots, lines, numbers, or icons to anchor each section
|
||||
5. **Avoid Clutter**: Descriptions one line max or omit entirely
|
||||
|
||||
### Content Elements
|
||||
|
||||
1. **Page Title** — Always required ("Table of Contents", "Agenda", "Overview")
|
||||
2. **Section Numbers** — Consistent format (01, 02... or I, II...)
|
||||
3. **Section Titles** — Clear and concise
|
||||
4. **Section Descriptions** — Optional one-line summaries
|
||||
5. **Visual Separators** — SVG dividers or spacing
|
||||
6. **Decorative Elements** — Subtle accent shapes
|
||||
7. **Page Number Badge** — **MANDATORY**
|
||||
|
||||
### Design Decisions
|
||||
|
||||
1. **Section Count**: 3 → vertical list; 4-6 → grid or compact; 7+ → multi-column
|
||||
2. **Description Length**: Long → vertical list; None → compact grid/cards
|
||||
3. **Tone**: Corporate → numbered list; Creative → card-based; Academic → Roman numerals
|
||||
4. **Consistency**: Match visual style of cover page
|
||||
|
||||
### Workflow
|
||||
|
||||
1. **Analyze**: Section list, count, presentation context
|
||||
2. **Choose Layout**: Based on section count and content
|
||||
3. **Plan Visual Hierarchy**: Numbering style, font sizes, spacing
|
||||
4. **Write Slide**: Use PptxGenJS. Use shapes for decorative elements. **MUST include page number badge.**
|
||||
5. **Verify**: Generate preview, extract text with markitdown, verify content and badge.
|
||||
|
||||
---
|
||||
|
||||
## 3. Section Divider
|
||||
|
||||
- **Use for**: Clear transitions between major parts
|
||||
- **Content**: Section number + title (+ optional 1-2 line intro)
|
||||
|
||||
### Layout Options
|
||||
|
||||
**Bold Center** — Best for minimal, modern presentations
|
||||
```
|
||||
| 02 |
|
||||
| SECTION TITLE |
|
||||
| Optional intro line |
|
||||
```
|
||||
|
||||
**Left-Aligned with Accent Block** — Best for corporate, structured presentations
|
||||
```
|
||||
| ████ | 02 |
|
||||
| ████ | SECTION TITLE |
|
||||
| ████ | Optional intro line |
|
||||
```
|
||||
|
||||
**Split Background** — Best for high-contrast, dramatic transitions
|
||||
```
|
||||
| ██████████ | SECTION TITLE |
|
||||
| ██ 02 ██ | Optional intro |
|
||||
| ██████████ | |
|
||||
```
|
||||
|
||||
**Full-Bleed Background with Overlay** — Best for creative, bold presentations
|
||||
```
|
||||
| ████████████████████████████████████ |
|
||||
| ████ large 02 █████████ |
|
||||
| ████ SECTION TITLE █████████ |
|
||||
| ████████████████████████████████████ |
|
||||
```
|
||||
|
||||
### Font Size Hierarchy
|
||||
|
||||
| Element | Recommended Size | Notes |
|
||||
|---------|-----------------|-------|
|
||||
| Section Number | 72-120px | Bold, accent color or semi-transparent |
|
||||
| Section Title | 36-48px | Bold, clear, primary text color |
|
||||
| Intro Text | 16-20px | Light weight, muted color, optional |
|
||||
|
||||
**Key Principles:**
|
||||
1. **Dramatic Number**: Section number = most prominent visual element
|
||||
2. **Strong Title**: Large but clearly secondary to the number
|
||||
3. **Minimal Content**: Just number + title + optional one-liner
|
||||
4. **Breathing Room**: Leave generous whitespace — dividers are pause moments
|
||||
|
||||
### Content Elements
|
||||
|
||||
1. **Section Number** — Always required. Format: `01`, `02`... or `I`, `II`... Match TOC style.
|
||||
2. **Section Title** — Always required. Clear, concise.
|
||||
3. **Intro Text** — Optional 1-2 line description.
|
||||
4. **Decorative Elements** — SVG accent shapes (bars, lines, geometric blocks).
|
||||
5. **Page Number Badge** — **MANDATORY**.
|
||||
|
||||
### Design Decisions
|
||||
|
||||
1. **Tone**: Corporate → accent block; Creative → full-bleed; Minimal → bold center
|
||||
2. **Color**: Strong palette color for background/accent; high-contrast text
|
||||
3. **Consistency**: Same divider style across all dividers in one presentation
|
||||
4. **Contrast with content slides**: Visually distinct (different background color, more whitespace)
|
||||
|
||||
### Workflow
|
||||
|
||||
1. **Analyze**: Section number, title, optional intro
|
||||
2. **Choose Layout**: Based on content and tone
|
||||
3. **Write Slide**: Use PptxGenJS. Use shapes for decorative elements. **MUST include page number badge.**
|
||||
4. **Verify**: Generate preview, extract text, verify content and badge.
|
||||
|
||||
---
|
||||
|
||||
## 4. Content Page
|
||||
|
||||
Pick a subtype based on the content. Each content slide belongs to exactly ONE subtype:
|
||||
|
||||
### Subtypes
|
||||
|
||||
**Text** — Bullets, quotes, or short paragraphs
|
||||
- Must still include icons or SVG shapes — never plain text only
|
||||
```
|
||||
| SLIDE TITLE |
|
||||
| * Bullet point one |
|
||||
| * Bullet point two |
|
||||
| * Bullet point three |
|
||||
```
|
||||
|
||||
**Mixed Media** — Two-column or half-bleed image + text
|
||||
```
|
||||
| SLIDE TITLE |
|
||||
| Text content | [Image/Visual] |
|
||||
| and bullets | |
|
||||
```
|
||||
|
||||
**Data Visualization** — Chart (SVG bar/progress/ring) + takeaways
|
||||
- Must include data source
|
||||
```
|
||||
| SLIDE TITLE |
|
||||
| [SVG Chart] | Key Takeaway 1 |
|
||||
| | Key Takeaway 2 |
|
||||
| Source: xxx |
|
||||
```
|
||||
|
||||
**Comparison** — Side-by-side columns or cards (A vs B, pros/cons)
|
||||
```
|
||||
| SLIDE TITLE |
|
||||
| ┌─ Option A ─┐ ┌─ Option B ─┐ |
|
||||
| │ Detail 1 │ │ Detail 1 │ |
|
||||
| └────────────┘ └────────────┘ |
|
||||
```
|
||||
|
||||
**Timeline / Process** — Steps with arrows, journey, phases
|
||||
```
|
||||
| SLIDE TITLE |
|
||||
| [1] ──→ [2] ──→ [3] ──→ [4] |
|
||||
| Step Step Step Step |
|
||||
```
|
||||
|
||||
**Image Showcase** — Hero image, gallery, visual-first layout
|
||||
```
|
||||
| SLIDE TITLE |
|
||||
| ┌────────────────────────────────┐ |
|
||||
| │ [Hero Image] │ |
|
||||
| └────────────────────────────────┘ |
|
||||
| Caption or supporting text |
|
||||
```
|
||||
|
||||
### Font Size Hierarchy
|
||||
|
||||
| Element | Recommended Size | Notes |
|
||||
|---------|-----------------|-------|
|
||||
| Slide Title | 36-44px | Bold, top of slide |
|
||||
| Section Header | 20-24px | Bold, for sub-sections within slide |
|
||||
| Body Text | 14-16px | Regular weight, left-aligned |
|
||||
| Captions / Source | 10-12px | Muted color, smallest text |
|
||||
| Stat Callout | 60-72px | Large bold numbers for key statistics |
|
||||
|
||||
**Key Principles:**
|
||||
1. **Left-align body text** — never center paragraphs or bullet lists
|
||||
2. **Size contrast** — title must be 36pt+ to stand out from 14-16pt body
|
||||
3. **Visual elements required** — every content slide must have at least one non-text element
|
||||
4. **Breathing room** — 0.5" minimum margins, 0.3-0.5" between content blocks
|
||||
|
||||
### Content Elements
|
||||
|
||||
1. **Slide Title** — Always required, top of slide
|
||||
2. **Body Content** — Text, bullets, data, or comparisons based on subtype
|
||||
3. **Visual Element** — Image, chart, icon, or SVG shape — always required
|
||||
4. **Source / Caption** — When showing data or external content
|
||||
5. **Page Number Badge** — **MANDATORY**
|
||||
|
||||
### Design Decisions
|
||||
|
||||
1. **Subtype**: Determine first — drives the entire layout
|
||||
2. **Content Volume**: Dense → multi-column or smaller font; Light → larger elements with more whitespace
|
||||
3. **Data vs Narrative**: Data-heavy → charts + stat callouts; Story-driven → images + quotes
|
||||
4. **Variety**: Each content slide should use a different layout from the previous one
|
||||
5. **Consistency**: Typography, colors, and spacing must match the rest of the presentation
|
||||
|
||||
### Workflow
|
||||
|
||||
1. **Analyze**: Content, determine subtype, plan layout
|
||||
2. **Choose Layout**: Best fit for subtype and content volume
|
||||
3. **Write Slide**: Use PptxGenJS. Use shapes for charts, decorative elements, icons. **MUST include page number badge.**
|
||||
4. **Verify**: Generate preview as `slide-XX-preview.pptx`. Extract text with markitdown, verify all content present, no placeholder text, badge included.
|
||||
|
||||
---
|
||||
|
||||
## 5. Summary / Closing Page
|
||||
|
||||
- **Use for**: Wrap-up + action
|
||||
- **Content**: Key takeaways, CTA/next steps, contact/QR, thank-you
|
||||
|
||||
### Layout Options
|
||||
|
||||
**Key Takeaways** — Best for educational, corporate, data-driven presentations
|
||||
```
|
||||
| KEY TAKEAWAYS |
|
||||
| ✓ Takeaway one |
|
||||
| ✓ Takeaway two |
|
||||
| ✓ Takeaway three |
|
||||
```
|
||||
|
||||
**CTA / Next Steps** — Best for sales pitches, proposals, project kick-offs
|
||||
```
|
||||
| NEXT STEPS |
|
||||
| [1] Action item one |
|
||||
| [2] Action item two |
|
||||
| Contact: email@example.com |
|
||||
```
|
||||
|
||||
**Thank You / Contact** — Best for conference talks, keynotes
|
||||
```
|
||||
| THANK YOU |
|
||||
| name@company.com |
|
||||
| @handle | website.com |
|
||||
```
|
||||
|
||||
**Split Recap** — Best for presentations needing both recap and action
|
||||
```
|
||||
| SUMMARY | NEXT STEPS |
|
||||
| * Point one | Contact us at |
|
||||
| * Point two | email@co.com |
|
||||
| * Point three | [QR Code] |
|
||||
```
|
||||
|
||||
### Font Size Hierarchy
|
||||
|
||||
| Element | Recommended Size | Notes |
|
||||
|---------|-----------------|-------|
|
||||
| Closing Title ("Thank You" / "Summary") | 48-72px | Bold, commanding |
|
||||
| Takeaway / Action Item | 18-24px | Clear, scannable |
|
||||
| Supporting Text | 14-16px | Regular weight |
|
||||
| Contact Info | 14-16px | Muted color |
|
||||
|
||||
**Key Principles:**
|
||||
1. **Strong closing statement**: Main message should be largest, most prominent
|
||||
2. **Scannable items**: Takeaways/action items concise (one line each)
|
||||
3. **Contact clarity**: Legible but not dominant
|
||||
4. **Memorable finish**: Confident, polished ending
|
||||
|
||||
### Content Elements
|
||||
|
||||
1. **Closing Title** — Always required
|
||||
2. **Takeaway Points** — 3-5 concise summary points (if applicable)
|
||||
3. **Call to Action** — Clear next steps (if applicable)
|
||||
4. **Contact Info** — Email, website, social handles (if provided)
|
||||
5. **Decorative Elements** — SVG accents for visual consistency
|
||||
6. **Page Number Badge** — **MANDATORY**
|
||||
|
||||
### Design Decisions
|
||||
|
||||
1. **Closing Type**: Recap, CTA, thank-you, or combination
|
||||
2. **Content Volume**: Many takeaways → list; Simple closing → centered thank-you
|
||||
3. **Audience Action**: Audience needs to do something → CTA; Informational → takeaways
|
||||
4. **Tone Consistency**: Match energy of cover page
|
||||
5. **Visual Distinction**: Special but not disconnected from the rest
|
||||
|
||||
### Workflow
|
||||
|
||||
1. **Analyze**: Closing content — takeaways, CTA, contact, thank-you
|
||||
2. **Choose Layout**: Based on content type
|
||||
3. **Write Slide**: Use PptxGenJS. Use shapes for decorative elements. **MUST include page number badge.**
|
||||
4. **Verify**: Generate preview, extract text, verify content and badge.
|
||||
|
||||
---
|
||||
|
||||
## Additional Layout Patterns
|
||||
|
||||
Use these across content slides for visual variety:
|
||||
|
||||
- **Two-column** (text left, illustration right)
|
||||
- **Icon + text rows** (icon in colored circle, bold header, description below)
|
||||
- **2x2 or 2x3 grid** (image on one side, grid of content blocks on other)
|
||||
- **Half-bleed image** (full left or right side) with content overlay
|
||||
- **Large stat callouts** (big numbers 60-72pt with small labels below)
|
||||
- **Comparison columns** (before/after, pros/cons)
|
||||
- **Timeline or process flow** (numbered steps, arrows)
|
||||
- **Icons in small colored circles** next to section headers
|
||||
- **Italic accent text** for key stats or taglines
|
||||
Reference in New Issue
Block a user