
Powerpoint Presentations
- 63 installs
- 186 repo stars
- Updated August 4, 2026
- aws-samples/sample-strands-agent-with-agentcore
powerpoint-presentations is a Claude skill that creates, modifies, and manages PowerPoint decks using PptxGenJS and template-aware workflows.
About
This skill lets an agent create, modify, and manage PowerPoint presentations, either from scratch with PptxGenJS or from an uploaded .pptx template. The template path preserves the slide master, theme, logo, and footer while swapping in new content. A developer uses it when an assistant needs to produce polished slide decks. It includes extensive design guidance on palettes, typography, layouts, and preview verification.
- Creates, modifies, and manages PowerPoint presentations with PptxGenJS
- Supports create-from-scratch and create-from-template workflows that preserve masters and theme
- Ships detailed design guidance: palettes, typography, layouts, and common mistakes to avoid
Powerpoint Presentations by the numbers
- 63 all-time installs (skills.sh)
- Ranked #354 of 688 Office & Documents skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
powerpoint-presentations capabilities & compatibility
- Capabilities
- slide generation · deck editing
- Use cases
- presentations
- Pricing
- Free
What powerpoint-presentations says it does
Create, modify, and manage PowerPoint presentations.
npx skills add https://github.com/aws-samples/sample-strands-agent-with-agentcore --skill powerpoint-presentationsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 63 |
|---|---|
| repo stars | ★ 186 |
| Last updated | August 4, 2026 |
| Repository | aws-samples/sample-strands-agent-with-agentcore ↗ |
What it does
Generate or edit a PowerPoint deck from scratch or from a template while preserving the template's theme.
Who is it for?
Producing polished slide decks from scratch or from an uploaded .pptx template with design guidance.
Skip if: Non-slide document formats.
When should I use this skill?
The user asks to create, edit, or manage a PowerPoint presentation or slide deck.
What you get
A designed .pptx deck built from scratch or from a template with preserved master, theme, logo, and footer.
- PowerPoint .pptx deck
- template-based slide deck
By the numbers
- 10 color-palette themes documented
- max 4 bullets per slide guidance
Files
PowerPoint Presentations
Quick Reference
| Task | How |
|---|---|
| Create from scratch | get_slide_design_reference → create_presentation (PptxGenJS). Read pptxgenjs.md. |
| Create from template | get_presentation_layouts → delete_slides (strip content) → add_slide → update_slide_content. Do NOT use `create_presentation`. |
| Edit existing | analyze_presentation → update_slide_content. Read editing-guide.md. |
| Verify | preview_presentation_slides after every change |
Design Ideas
Don't create boring slides. Plain bullets on a white background won't impress anyone.
Before Starting
- Pick a bold, content-informed color palette: The palette should feel designed for THIS topic.
- Dominance over equality: One color dominates (60-70% visual weight), with 1-2 supporting tones and one sharp accent. Never give all colors equal weight.
- Dark/light contrast: Dark backgrounds for title + conclusion slides, lighter tints for content slides. Or commit to dark throughout for a premium feel.
- Commit to a visual motif: Pick ONE distinctive element and repeat it — rounded image frames, icons in colored circles, thick single-side borders.
Color Palettes
Choose colors that match your topic — don't default to generic blue.
| Theme | Primary | Secondary | Accent |
|---|---|---|---|
| Midnight Executive | 1E2761 (navy) | CADCFC (ice blue) | FFFFFF (white) |
| Teal Trust | 028090 (teal) | 00A896 (seafoam) | 02C39A (mint) |
| Forest & Moss | 2C5F2D (forest) | 97BC62 (moss) | F5F5F5 (cream) |
| Berry & Cream | 6D2E46 (berry) | A26769 (dusty rose) | ECE2D0 (cream) |
| Coral Energy | F96167 (coral) | F9E795 (gold) | 2F3C7E (navy) |
| Ocean Gradient | 065A82 (ocean) | 1C7293 (teal) | 21295C (midnight) |
| Charcoal Minimal | 36454F (charcoal) | F2F2F2 (off-white) | 212121 (black) |
| Cherry Bold | 990011 (cherry) | FCF6F5 (off-white) | 2F3C7E (navy) |
| Sage Calm | 84B59F (sage) | 69A297 (eucalyptus) | 50808E (slate) |
| Warm Terracotta | B85042 (terracotta) | E7E8D1 (sand) | A7BEAE (sage) |
For Each Slide
Every slide needs a visual element — image, chart, icon, or shape. Text-only slides are forgettable.
Layout options:
- Two-column (text left, illustration right)
- Icon + text rows (icon in colored circle, bold header, description below)
- 2x2 or 2x3 grid (image one side, content blocks the other)
- Half-bleed image (full left or right) with content overlay
Data display:
- Large stat callouts (big numbers 60-72pt with small labels below)
- Comparison columns (before/after, pros/cons, side-by-side options)
- Timeline or process flow (numbered steps, arrows)
Visual polish:
- Icons in small colored circles next to section headers
- Italic accent text for key stats or taglines
Typography
| Header Font | Body Font |
|---|---|
| Georgia | Calibri |
| Arial Black | Arial |
| Calibri Bold | Calibri Light |
| Cambria | Calibri |
| Trebuchet MS | Calibri |
| Element | Size |
|---|---|
| Slide title | 36-44pt bold |
| Section header | 20-24pt bold |
| Body text | 14-16pt |
| Captions | 10-12pt muted |
Font pairings: Georgia + Calibri (classic), Arial Black + Arial (modern), Calibri Bold + Calibri Light (corporate). Left-align body text; center only titles and stats.
Spacing
- 0.5" minimum margins from edges
- 0.3-0.5" between content blocks
- 0.5"+ breathing room below titles
Avoid (Common Mistakes)
- Plain bullets on white background — always fill slides with a palette color
- Default PowerPoint blue (#4472C4) — signals "auto-generated"
- Don't repeat the same layout — vary columns, cards, and callouts across slides
- Don't center body text — left-align paragraphs; center only titles and stats
- Don't skimp on size contrast — titles need 36pt+ to stand out from 14-16pt body
- 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 shapes, icons, charts, or accent elements
- Don't forget text box padding — set
margin: 0when aligning text with shapes at same x-position - Don't use low-contrast elements — text AND icons need strong contrast against background
- NEVER use accent lines under titles — use whitespace or background color instead
- Don't overcrowd slides — max 4 bullets; split to multiple slides or use 2x2/3-column grid
See design-guide.md for visual element code patterns (accent bars, icon circles, side stripes, cards).
---
Workflow
A. Create from scratch (no template)
1. Call get_slide_design_reference for palette and layout ideas 2. Call create_presentation with slides parameter (PptxGenJS). Read pptxgenjs.md for the full API.
B. Create from a template (user uploaded a .pptx template)
Do NOT use `create_presentation` — that ignores the template entirely and recreates from scratch.
Instead, use the template file as the base: 1. get_presentation_layouts("template-name") — see available layout names 2. preview_presentation_slides — inspect visual style (colors, logo, footer, chrome elements) 3. delete_slides("template-name", [indices of all content slides], "working-name") — strip example content, keep masters/layouts 4. add_slide("working-name", layout_name, position, "working-name-v2") — add slides using the template's own layouts (inherits background, logo, footer automatically) 5. update_slide_content(...) — fill in text and images
This preserves the template's slide master, theme, logo, footer, and background — things create_presentation cannot replicate.
C. Edit existing presentation
Read editing-guide.md for detailed workflows. Then: analyze_presentation → identify element IDs → update_slide_content.
Verify
Call preview_presentation_slides after any modification. Assume there are problems — inspect carefully.
When continuing a deck across conversation turns: Do NOT re-preview existing slides just to check the design system. The palette, fonts, and layout decisions from the previous turn are already in the conversation history — use that. Only re-preview if you need to verify the visual state after a modification.
Rules
- Batch all edits in ONE
update_slide_contentcall. Parallel calls cause data loss. output_namemust differ frompresentation_name.- All slide indices are 0-based EXCEPT
preview_presentation_slideswhich uses 1-basedslide_numbers. - Filenames: letters, numbers, hyphens only.
---
QA (Required)
Assume there are problems. Your job is to find them.
Your first render is almost never perfect. Approach QA as a bug hunt, not a confirmation step.
Visual QA
Call preview_presentation_slides and visually inspect the screenshots. Look for:
- Overlapping elements (text through shapes, lines through words)
- Text overflow or cut off at edges
- Elements too close (< 0.3" gaps) or cards nearly touching
- Uneven gaps (large empty area in one place, cramped in another)
- Insufficient margin from slide edges (< 0.5")
- Columns or similar elements not aligned consistently
- Low-contrast text (light text on light background, dark text on dark background)
- Low-contrast icons without a contrasting background circle
- Text boxes too narrow causing excessive wrapping
- Inconsistent font sizes or styles across similar elements
Verification Loop
1. Generate → preview_presentation_slides → inspect screenshots 2. List issues found (if none found, look again more critically) 3. Fix with update_slide_content 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.
---
Tool Reference
get_slide_design_reference
Get design guidelines, color palettes, typography rules, and layout patterns.
| Parameter | Type | Required | Description |
|---|---|---|---|
topic | str | No (default "all") | "colors", "typography", "layouts", "pitfalls", "all" |
create_presentation
Create a new presentation with custom-designed slides (16:9 widescreen).
| Parameter | Type | Required | Description |
|---|---|---|---|
presentation_name | str | Yes | Filename without extension (letters, numbers, hyphens only) |
slides | list or null | Yes | List of {"custom_code": "..."} dicts, or null for blank |
Example tool_input:
{
"presentation_name": "my-deck",
"slides": [
{"custom_code": "let slide = pres.addSlide();\nslide.background = { color: '1E2761' };\nslide.addText('Welcome', { x: 0.6, y: 2.5, w: 10, h: 1.5, fontSize: 44, bold: true, color: 'FFFFFF', align: 'center' });"}
]
}IMPORTANT: custom_code uses pres in scope. Create slides with pres.addSlide(). Colors are 6-digit hex WITHOUT '#'. Do NOT reuse option objects across multiple addText/addShape calls. See pptxgenjs.md for full API.
analyze_presentation
Analyze structure with element IDs and positions for editing.
| Parameter | Type | Required | Description |
|---|---|---|---|
presentation_name | str | Yes | Presentation to analyze |
slide_index | int | No | Analyze a specific slide only |
include_notes | bool | No (default false) | Include speaker notes |
update_slide_content
Update one or more slides with operations in a single call.
| Parameter | Type | Required | Description |
|---|---|---|---|
presentation_name | str | Yes | Source file |
slide_updates | list | Yes | List of update operations |
output_name | str | Yes | Output filename (MUST differ from source) |
Supported actions per operation: set_text, replace_text, replace_image. See editing-guide.md for details.
add_slide
Add a new blank slide at a specific position.
| Parameter | Type | Required | Description |
|---|---|---|---|
presentation_name | str | Yes | Source presentation |
layout_name | str | Yes | Layout name from get_presentation_layouts |
position | int | Yes | 0-based index (-1 to append at end) |
output_name | str | Yes | Output filename |
After adding, populate content with update_slide_content.
delete_slides
| Parameter | Type | Required |
|---|---|---|
presentation_name | str | Yes |
slide_indices | list[int] | Yes (0-based) |
output_name | str | Yes |
move_slide
| Parameter | Type | Required |
|---|---|---|
presentation_name | str | Yes |
from_index | int | Yes (0-based) |
to_index | int | Yes (0-based) |
output_name | str | Yes |
duplicate_slide
| Parameter | Type | Required | Description |
|---|---|---|---|
presentation_name | str | Yes | |
source_index | int | Yes (0-based) | Slide to duplicate |
output_name | str | Yes | |
insert_position | int | No (default -1) | Where to insert copy; -1 appends after source |
update_slide_notes
| Parameter | Type | Required |
|---|---|---|
presentation_name | str | Yes |
slide_index | int | Yes (0-based) |
notes_text | str | Yes |
output_name | str | Yes |
list_my_powerpoint_presentations
List all presentations in workspace. No parameters needed.
get_presentation_layouts
Get available slide layouts from a presentation.
| Parameter | Type | Required |
|---|---|---|
presentation_name | str | Yes |
preview_presentation_slides
Get slide screenshots for visual inspection.
| Parameter | Type | Required | Description |
|---|---|---|---|
presentation_name | str | Yes | Presentation to preview |
slide_numbers | list[int] | Yes | 1-based slide numbers (not 0-based) |
UI Guidance (from tools-config)
Creating New Presentations:
- Use get_slide_design_reference() first to get design guidelines and color palettes
- create_presentation slides format: [{"custom_code": "let slide = pres.addSlide(); slide.addText(...)"}]
- Each custom_code snippet has
presin scope; create slides with pres.addSlide() - Color format: 6-digit hex WITHOUT '#' (e.g. '1E2761', not '#1E2761')
Editing Existing Presentations:
- Operations: set_text, replace_text, replace_image
- Batch all edits in 1 call (parallel calls = data loss)
- Output name must differ from source
- preview_presentation_slides first to check layout
Design Philosophy (MANDATORY for new presentations):
- CRITICAL: Choose ONE palette for the ENTIRE presentation. All slides must use the same primary and accent colors. Do NOT mix palettes across slides.
- Bold dominant background colors (60-70% slide coverage). NEVER use plain white backgrounds.
- Available palettes: Midnight Executive (#1E2761/#408EC6), Teal Trust (#0A1A2A/#028090), Forest & Moss (#2C5F2D/#97BC62), Berry & Cream (#ECE2D0/#6D2E46), Coral Energy (#1A1A2E/#FF6F61), Ocean Gradient (#065A82/#1B9AAA), Charcoal Minimal (#1C1C1E/#E8E8E8), Cherry Bold (#150E11/#990011), Sage Calm (#2D3A2D/#8FB96A)
- Dark slides for emphasis, lighter tints of the SAME palette for data slides.
- Every slide must have visual elements (shapes, accent bars, icon circles) — no text-only slides.
Typography:
- Titles: 36-44pt bold (Georgia or Arial Black). Body: 14-16pt (Calibri). Stats: 48-120pt bold.
- Font pairings: Georgia+Calibri (classic), Arial Black+Arial (modern), Calibri Bold+Calibri Light (corporate)
- Left-align body text. Center only titles and stats.
Spacing:
- 0.5"+ margins from edges. 0.3-0.5" gaps between elements. 0.5"+ breathing room below titles.
Anti-Patterns (AVOID):
- Plain bullets on white background
- Default PowerPoint blue (#4472C4)
- Accent lines directly under titles
- Text-only slides without visual elements
- More than 4 bullet points per slide
QA: Always use preview_presentation_slides after creation to verify appearance.
Rules:
- Names: letters, numbers, hyphens only
- Indices: 0-based
PowerPoint Design Guide
Visual patterns and detailed guidance for slide design. Load this when implementing slide visuals.
Using Palettes in Code (PptxGenJS)
// Example: Midnight Executive palette
// Colors are 6-digit hex WITHOUT '#'
const PRIMARY = "1E2761";
const ACCENT = "FFFFFF";
const ICE = "CADCFC";
let slide = pres.addSlide();
// Solid background
slide.background = { color: PRIMARY };
// Accent bar at bottom
slide.addShape(pres.shapes.RECTANGLE, {
x: 0, y: 7.1, w: 13.3, h: 0.4,
fill: { color: ACCENT }, line: { color: ACCENT }
});
// Title text
slide.addText("Slide Title", {
x: 0.6, y: 0.4, w: 10, h: 1.0,
fontSize: 40, bold: true, color: ACCENT,
fontFace: "Georgia", margin: 0
});Creating Lighter Tints
For data slides that need lighter backgrounds within the same palette:
// Slightly lighter than Midnight Executive primary for data slide background
const LIGHT_BG = "2A3578"; // Tint of 1E2761
slide.background = { color: LIGHT_BG };---
Visual Element Patterns
Accent bar (bottom)
slide.addShape(pres.shapes.RECTANGLE, {
x: 0, y: 7.1, w: 13.3, h: 0.4,
fill: { color: ACCENT }, line: { color: ACCENT }
});Icon circle
// ICE (secondary) fill + dark PRIMARY text = legible on any slide background
slide.addShape(pres.shapes.OVAL, {
x: 1.0, y: 2.0, w: 1.2, h: 1.2,
fill: { color: ICE }, line: { color: ICE }
});
slide.addText("★", {
x: 1.0, y: 2.0, w: 1.2, h: 1.2,
fontSize: 28, color: PRIMARY, align: "center", valign: "middle"
});Side stripe (left edge)
slide.addShape(pres.shapes.RECTANGLE, {
x: 0, y: 0, w: 0.4, h: 7.5,
fill: { color: ACCENT }, line: { color: ACCENT }
});Divider line
slide.addShape(pres.shapes.RECTANGLE, {
x: 1, y: 3.0, w: 11.3, h: 0.02,
fill: { color: ACCENT }, line: { color: ACCENT }
});Card with shadow
const makeShadow = () => ({ type: "outer", color: "000000", blur: 8, offset: 3, angle: 135, opacity: 0.15 });
slide.addShape(pres.shapes.RECTANGLE, {
x: 1.0, y: 1.5, w: 5.0, h: 2.5,
fill: { color: "FFFFFF" },
shadow: makeShadow()
});Always use a factory function for shadow objects — PptxGenJS mutates them in-place. See pptxgenjs.md.
Stat callout (large number)
slide.addText("87%", {
x: 1, y: 1.5, w: 4, h: 2,
fontSize: 80, bold: true, color: ACCENT,
align: "center", valign: "middle"
});
slide.addText("Customer Satisfaction", {
x: 1, y: 3.5, w: 4, h: 0.5,
fontSize: 14, color: ACCENT, align: "center"
});PowerPoint Editing Guide
Editing Existing Presentations
Step 1: Analyze Structure
Always call analyze_presentation first to get element IDs and positions.
{ "presentation_name": "my-deck", "slide_index": 0 }The response includes:
element_id: Unique identifier for each element (shape)text: Current text contentposition: Left, top, width, height in EMU (English Metric Units)placeholder_idx: Placeholder index (for template-based slides)
Step 2: Build Update Operations
update_slide_content accepts a list of slide_updates, each targeting a specific slide:
{
"presentation_name": "my-deck",
"output_name": "my-deck-v2",
"slide_updates": [
{
"slide_index": 0,
"operations": [
{
"action": "set_text",
"element_id": 2,
"text": "New Title"
}
]
}
]
}Available Actions
| Action | Required Fields | Description |
|---|---|---|
set_text | element_id, text | Replace all text in a shape |
replace_text | element_id, old_text, new_text | Replace specific text within a shape (preserves formatting) |
replace_image | element_id, image_path | Replace an existing image with a new one |
EMU Unit Reference
1 inch = 914400 EMU. Common slide dimensions (16:9):
- Slide width: 12192000 EMU (13.333 inches)
- Slide height: 6858000 EMU (7.5 inches)
When editing actions aren't enough
If you need to add completely new visual elements or restructure a slide:
- Use
create_presentationwith PptxGenJS to build a new deck from scratch - Use
add_slideto append a blank slide, thenset_textto populate existing placeholder shapes
Batch Editing Rules
- Always batch all slide updates into a single
update_slide_contentcall. - Multiple slides can be updated in one call by adding multiple entries to
slide_updates. - Never call
update_slide_contentmultiple times in sequence on the same file — the second call would overwrite the first. - The
output_namemust differ frompresentation_name. Use a versioning convention like-v2,-v3.
Common Patterns
Replace all text on a slide
{
"slide_updates": [
{
"slide_index": 0,
"operations": [
{ "action": "set_text", "element_id": 2, "text": "Updated Title" },
{ "action": "set_text", "element_id": 3, "text": "Updated Subtitle" }
]
}
]
}Replace specific text (preserve formatting)
{
"slide_updates": [
{
"slide_index": 1,
"operations": [
{ "action": "replace_text", "element_id": 3, "old_text": "Q3", "new_text": "Q4" }
]
}
]
}PptxGenJS Reference
The pres instance (PptxGenJS, LAYOUT_WIDE) is already in scope. Start with pres.addSlide().
Layout dimensions for LAYOUT_WIDE: 13.3" × 7.5"Other layouts:LAYOUT_16x910"×5.625" ·LAYOUT_16x1010"×6.25" ·LAYOUT_4x310"×7.5"
---
Text & Formatting
// 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 — letterSpacing is silently ignored)
slide.addText("SPACED TEXT", { x: 1, y: 1, w: 8, h: 1, charSpacing: 6 });
// Rich text arrays (partial formatting)
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 between lines)
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)
// Set margin: 0 when aligning text precisely with shapes/icons at the same x-position
slide.addText("Title", { x: 0.5, y: 0.3, w: 9, h: 0.6, margin: 0 });---
Lists & Bullets
// ✅ CORRECT: Multiple bullets using array
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 bullet characters
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
// Rectangle
slide.addShape(pres.shapes.RECTANGLE, {
x: 0.5, y: 0.8, w: 1.5, h: 3.0,
fill: { color: "1E2761" }, line: { color: "000000", width: 2 }
});
// Oval / circle
slide.addShape(pres.shapes.OVAL, { x: 4, y: 1, w: 2, h: 2, fill: { color: "408EC6" } });
// Line with dash
slide.addShape(pres.shapes.LINE, {
x: 1, y: 3, w: 5, h: 0, line: { color: "408EC6", width: 3, dashType: "dash" }
});
// Transparency
slide.addShape(pres.shapes.RECTANGLE, {
x: 1, y: 1, w: 3, h: 2,
fill: { color: "0088CC", transparency: 50 }
});
// Rounded 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 | Range | Notes |
|---|---|---|
type | "outer", "inner" | |
color | 6-char hex, no # | Never encode opacity in color string |
blur | 0-100 pt | |
offset | 0-200 pt | Must be non-negative |
angle | 0-359 degrees | 135 = bottom-right, 270 = upward |
opacity | 0.0-1.0 |
To cast a shadow upward (e.g. footer bar), use angle: 270 with positive offset — do not use negative offset.
Gradient fills are not natively supported. Use a gradient image as slide background instead.
---
Images
// 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 });
// Options
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
altText: "Description"
});
// Sizing modes
{ sizing: { type: 'contain', w: 4, h: 3 } } // Fit inside, preserve ratio
{ sizing: { type: 'cover', w: 4, h: 3 } } // Fill area, preserve ratio (may crop)
{ sizing: { type: 'crop', x: 0.5, y: 0.5, w: 2, h: 2 } } // Cut specific portionPreserve aspect ratio:
const origWidth = 1978, origHeight = 923, maxHeight = 3.0;
const calcWidth = maxHeight * (origWidth / origHeight);
const centerX = (13.3 - calcWidth) / 2; // LAYOUT_WIDE is 13.3" wide
slide.addImage({ path: "image.png", x: centerX, y: 1.2, w: calcWidth, h: maxHeight });---
Slide Backgrounds
// Solid color
slide.background = { color: "1E2761" };
// Image
slide.background = { path: "https://example.com/bg.jpg" };
slide.background = { data: "image/png;base64,iVBORw0KGgo..." };---
Tables
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 and styled headers
let tableData = [
[{ text: "Header", options: { fill: { color: "1E2761" }, color: "FFFFFF", bold: true } }, "Cell"],
[{ text: "Merged", options: { colspan: 2 } }]
];
slide.addTable(tableData, { x: 1, y: 3.5, w: 8, colW: [4, 4] });---
Charts
// 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: "Trend", 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 });Modern, clean chart styling — default charts look dated, apply these:
slide.addChart(pres.charts.BAR, chartData, {
x: 0.5, y: 1, w: 9, h: 4, barDir: "col",
chartColors: ["0D9488", "14B8A6", "5EEAD4"], // Match your palette
chartArea: { fill: { color: "FFFFFF" }, roundedCorners: true },
catAxisLabelColor: "64748B", // Muted axis labels
valAxisLabelColor: "64748B",
valGridLine: { color: "E2E8F0", size: 0.5 }, // Subtle grid (value only)
catGridLine: { style: "none" },
showValue: true,
dataLabelPosition: "outEnd",
dataLabelColor: "1E293B",
showLegend: false, // Hide for single series
});Key chart options: chartColors, chartArea, catGridLine/valGridLine, lineSmooth, legendPos ("b"/"t"/"l"/"r"/"tr")
Available chart types: BAR, LINE, PIE, DOUGHNUT, SCATTER, BUBBLE, RADAR
---
Common Pitfalls
⚠️ These cause file corruption, visual bugs, or broken output.
1. NEVER use "#" with hex colors — corrupts file
color: "FF0000" // ✅
color: "#FF0000" // ❌2. NEVER encode opacity in hex color strings — 8-char hex corrupts the file
shadow: { color: "00000020" } // ❌ CORRUPTS FILE
shadow: { color: "000000", opacity: 0.12 } // ✅3. Use `bullet: true`, never unicode "•" (creates double bullets)
4. Use `breakLine: true` between items in text arrays
5. Avoid `lineSpacing` with bullets — causes excessive gaps; use paraSpaceAfter instead
6. NEVER reuse option objects across calls — PptxGenJS mutates objects in-place (converts values to EMU). Sharing one object between multiple addText/addShape calls corrupts the second shape.
// ❌ Wrong: shadow object gets mutated after first call
const shadow = { type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.15 };
slide.addShape(pres.shapes.RECTANGLE, { x:1, y:1, w:3, h:2, fill:{color:"FFF"}, shadow });
slide.addShape(pres.shapes.RECTANGLE, { x:5, y:1, w:3, h:2, fill:{color:"FFF"}, shadow });
// ✅ Correct: factory function creates fresh object each time
const makeShadow = () => ({ type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.15 });
slide.addShape(pres.shapes.RECTANGLE, { x:1, y:1, w:3, h:2, fill:{color:"FFF"}, shadow: makeShadow() });
slide.addShape(pres.shapes.RECTANGLE, { x:5, y:1, w:3, h:2, fill:{color:"FFF"}, shadow: makeShadow() });7. Don't use `ROUNDED_RECTANGLE` with accent borders — rectangular overlay bars won't cover rounded corners
// ❌ 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"} });
// ✅ 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"} });---
Spatial Reference (LAYOUT_WIDE: 13.3" × 7.5")
Use these as mental anchors when placing elements. All coordinates are in inches.
Slide zones
┌─────────────────────────────────────────┐ y=0
│ safe margin top: 0.4" │
│ ┌───────────────────────────────────┐ │ y=0.4
│ │ Title zone (~0.5–1.2" tall) │ │
│ ├───────────────────────────────────┤ │ y=1.2–1.5
│ │ │ │
│ │ Content zone (~4.5–5.5" tall) │ │
│ │ │ │
│ └───────────────────────────────────┘ │ y=6.8–7.1
│ safe margin bottom: 0.4" │
└─────────────────────────────────────────┘ y=7.5
x=0 x=13.3
safe margin left/right: 0.5–0.6"Font size → visual height
| Font size | Text box height needed | Typical use |
|---|---|---|
| 44pt bold | ~0.7" | Main title |
| 32–36pt bold | ~0.55" | Section title |
| 24pt bold | ~0.42" | Card header / subtitle |
| 18pt | ~0.32" | Large body |
| 16pt | ~0.28" | Normal body |
| 14pt | ~0.25" | Small body |
| 11–12pt | ~0.20" | Caption / footnote |
Add 0.1–0.15" padding to the h value to avoid clipping. Multi-line text multiplies height linearly.
Horizontal space budget
At common font sizes, approximate characters per line for a given width:
| Width | 16pt | 20pt | 24pt |
|---|---|---|---|
| 4" | ~55 chars | ~44 chars | ~36 chars |
| 6" | ~82 chars | ~66 chars | ~55 chars |
| 8" | ~110 chars | ~88 chars | ~73 chars |
| 11" | ~150 chars | ~120 chars | ~100 chars |
These are rough estimates (varies by font face). Wrap generously — narrow boxes cause unexpected wrapping.
Common layout patterns (inches)
// Full-width title bar (left of chrome)
{ x: 0.6, y: 0.35, w: 11.5, h: 0.75 } // 44pt title
// Two-column split
// Left column: x:0.5, w:5.9
// Right column: x:6.9, w:5.9
// Three-column split
// Col 1: x:0.5, w:3.7
// Col 2: x:4.8, w:3.7
// Col 3: x:9.1, w:3.7
// 2×2 grid (cards)
// Top-left: x:0.5, y:1.5, w:5.9, h:2.3
// Top-right: x:6.9, y:1.5, w:5.9, h:2.3
// Bottom-left: x:0.5, y:4.1, w:5.9, h:2.3
// Bottom-right: x:6.9, y:4.1, w:5.9, h:2.3
// Large stat callout
{ x: 1.0, y: 1.8, w: 5.0, h: 2.2 } // 72pt number + 14pt label below
// Bottom accent bar (above chrome bar)
{ x: 0, y: 7.1, w: 13.3, h: 0.4 }
// Left side stripe (chrome)
{ x: 0, y: 0, w: 0.15, h: 7.5 }Gaps and spacing rules
- Slide edge → first element: 0.5" minimum (use 0.6" for comfort)
- Between sibling elements: 0.2–0.3" minimum; 0.4–0.5" for breathing room
- Title bottom → content top: 0.3–0.5"
- Content bottom → slide edge / bar: 0.3" minimum
- Card internal padding (text inside a card shape): 0.2" on all sides → offset text box by 0.2" from shape edges
---
Quick Reference
- Shapes:
pres.shapes.RECTANGLE,OVAL,LINE,ROUNDED_RECTANGLE - Charts:
pres.charts.BAR,LINE,PIE,DOUGHNUT,SCATTER,BUBBLE,RADAR - Alignment:
"left","center","right" - Data label positions:
"outEnd","inEnd","center"
Related skills
FAQ
Does it respect uploaded templates?
Yes, the create-from-template workflow uses get_presentation_layouts and add_slide and preserves the slide master, theme, logo, and footer.
How do you verify slides?
Call preview_presentation_slides after every change to inspect the result.