Nano Banana Pro
Agent skill for nano-banana-pro
Presentation creation, editing, and analysis. When Claude needs to work with presentations (.pptx files) for: (1) Creating new presentations, (2) Modifying or editing content, (3) Working with layouts, (4) Adding comments or speaker notes, or any other presentation tasks
Sign in to like and favorite skills
A user may ask you to create, edit, or analyze the contents of a .pptx file. A .pptx file is essentially a ZIP archive containing XML files and other resources that you can read or edit. You have different tools and workflows available for different tasks.
If you just need to read the text contents of a presentation, you should convert the document to markdown:
# Convert document to markdown python -m markitdown path-to-file.pptx
You need raw XML access for: comments, speaker notes, slide layouts, animations, design elements, and complex formatting. For any of these features, you'll need to unpack a presentation and read its raw XML contents.
python ooxml/scripts/unpack.py <office_file> <output_dir>
Note: The unpack.py script is located at
skills/pptx/ooxml/scripts/unpack.py relative to the project root. If the script doesn't exist at this path, use find . -name "unpack.py" to locate it.
ppt/presentation.xml - Main presentation metadata and slide referencesppt/slides/slide{N}.xml - Individual slide contents (slide1.xml, slide2.xml, etc.)ppt/notesSlides/notesSlide{N}.xml - Speaker notes for each slideppt/comments/modernComment_*.xml - Comments for specific slidesppt/slideLayouts/ - Layout templates for slidesppt/slideMasters/ - Master slide templatesppt/theme/ - Theme and styling informationppt/media/ - Images and other media filesWhen given an example design to emulate: Always analyze the presentation's typography and colors first using the methods below:
ppt/theme/theme1.xml for colors (<a:clrScheme>) and fonts (<a:fontScheme>)ppt/slides/slide1.xml for actual font usage (<a:rPr>) and colors<a:solidFill>, <a:srgbClr>) and font references across all XML filesWhen creating a new PowerPoint presentation from scratch, use the html2pptx workflow to convert HTML slides to PowerPoint with accurate positioning.
CRITICAL: Before creating any presentation, analyze the content and choose appropriate design elements:
Requirements:
Choosing colors creatively:
Example color palettes (use these to spark creativity - choose one, adapt it, or create your own):
Geometric Patterns:
Border & Frame Treatments:
Typography Treatments:
Chart & Data Styling:
Layout Innovations:
Background Treatments:
When creating slides with charts or tables:
⚠️ CRITICAL: Follow these steps IN ORDER. Each step creates ONE file before moving to the next.
Read
completely from start to finish. NEVER set any range limits. This file contains:html2pptx.md
IMPORTANT: Create separate HTML files - one file for each slide.
Example for a 3-slide presentation:
<!-- slide1.html --> <!DOCTYPE html> <html> <head> <style> body { width: 720pt; height: 405pt; /* 16:9 layout */ margin: 0; padding: 48pt; box-sizing: border-box; font-family: Arial, sans-serif; background: #1C2833; } h1 { font-size: 36pt; color: #F4F6F6; margin: 0 0 24pt 0; } p { font-size: 18pt; color: #F4F6F6; } </style> </head> <body> <h1>Slide 1 Title</h1> <p>Content for first slide</p> </body> </html>
<!-- slide2.html --> <!DOCTYPE html> <html> <head> <style> body { width: 720pt; height: 405pt; margin: 0; padding: 48pt; box-sizing: border-box; font-family: Arial, sans-serif; background: #2E4053; } h1 { font-size: 36pt; color: #F4F6F6; margin: 0 0 24pt 0; } p { font-size: 18pt; color: #F4F6F6; } </style> </head> <body> <h1>Slide 2 Title</h1> <p>Content for second slide</p> <!-- Placeholder for chart --> <div id="chart1" class="placeholder" style="width: 600pt; height: 260pt;"></div> </body> </html>
<!-- slide3.html - similar structure -->
Critical HTML Rules:
<p>, <h1>-<h6>, <ul>, <ol> tagsclass="placeholder" with unique id for chart/image areasCRITICAL - Script Path Resolution
When generating a script that uses
html2pptx.js, you MUST use the correct path pattern. The skills connector sets the SKILL_DIR environment variable pointing to this skill's root directory.
Required pattern for path resolution:
const path = require('path'); // CRITICAL: Use SKILL_DIR environment variable to locate html2pptx // SKILL_DIR points to the skill's root (e.g., D:\ops-data\agent-skills\pptx) // This works regardless of where the script is run from const skillDir = process.env.SKILL_DIR; if (!skillDir) { console.error('ERROR: SKILL_DIR environment variable not set'); console.error('This script must be run via the skills connector'); process.exit(1); } const html2pptx = require(path.join(skillDir, 'scripts', 'html2pptx'));
Why this pattern is required:
require('./scripts/html2pptx') - Fails if script runs from a different directoryrequire('../agent-skills/pptx/scripts/html2pptx') - Breaks if connector mount path changesrequire(path.join(process.env.SKILL_DIR, 'scripts', 'html2pptx')) - Always works correctlyFull example script:
// create-presentation.js const pptxgen = require('pptxgenjs'); const path = require('path'); // CRITICAL: Use SKILL_DIR environment variable to locate html2pptx const skillDir = process.env.SKILL_DIR; if (!skillDir) { console.error('ERROR: SKILL_DIR environment variable not set'); console.error('This script must be run via the skills connector'); process.exit(1); } const html2pptx = require(path.join(skillDir, 'scripts', 'html2pptx')); async function main() { try { console.log('Creating presentation...'); console.log('SKILL_DIR:', skillDir); const pptx = new pptxgen(); pptx.layout = 'LAYOUT_16x9'; pptx.title = 'My Presentation'; // Convert each HTML file to a slide // ONE html2pptx() call per HTML file await html2pptx(path.join(__dirname, 'slide1.html'), pptx); await html2pptx(path.join(__dirname, 'slide2.html'), pptx); await html2pptx(path.join(__dirname, 'slide3.html'), pptx); // Add charts to placeholders if needed // (See complete example in html2pptx.md) await pptx.writeFile({ fileName: 'output.pptx' }); console.log('✓ Presentation created: output.pptx'); process.exit(0); } catch (error) { console.error('✗ Error:', error.message); console.error('Stack trace:', error.stack); process.exit(1); } } main();
Use run_script with absolute path from write response
After writing the script in Step 3, the write response includes the full absolute path. Use this exact path with
run_script and add the skillId parameter.
✅ Correct approach:
// Step 3 write response: { "path": "D:\\ops-data\\create-presentation.js" } // Step 4: Run using the FULL PATH from response { "action": "remote_tool_call", "target": "filesystem", "params": { "agent_id": "local-dev", "connector_id": "local-files", // Same connector you used for write "command": "run_script", "path": "D:\\ops-data\\create-presentation.js", // FULL path from write response "skillId": "pptx", // Sets SKILL_DIR environment variable "type": "node" } }
How skillId works:
SKILL_DIR=/path/to/agent-skills/pptxprocess.env.SKILL_DIR to locate html2pptx.jsCheck the result:
exitCode: 0 → Success! PPTX createdexitCode: 1 → Read stdout/stderr error message, fix issues, retryGenerate thumbnails and inspect:
python scripts/thumbnail.py output.pptx workspace/thumbnails --cols 4
Read thumbnail image and check for:
If issues found, adjust HTML and regenerate (return to Step 2).
📋 Summary - Files to Create:
slide1.html, slide2.html, slide3.html, ... (ONE file per slide)create-presentation.js (ONE script that calls html2pptx() for each HTML file)node create-presentation.js → output.pptx createdIf your script fails with exit code 1:
The error output from
run_script should contain diagnostic information. Look for:
Module not found errors:
Error: Cannot find module './scripts/html2pptx'
Cause: Not using
process.env.SKILL_DIR for path resolution
Fix: Update require statement to use path.join(process.env.SKILL_DIR, 'scripts', 'html2pptx')
SKILL_DIR not set:
ERROR: SKILL_DIR environment variable not set
Cause: Missing
skillId parameter in run_script call
Fix: Add "skillId": "pptx" to the params when calling run_script. This sets the SKILL_DIR environment variable that your script needs to locate html2pptx.
HTML conversion errors:
Error: HTML file must have exactly one body element
Cause: Invalid HTML structure Fix: Verify HTML files have proper structure with single
<html>, <head>, and <body> tags
Dimension errors:
Error: Body dimensions must be 720pt × 405pt for 16:9
Cause: Incorrect HTML body dimensions Fix: Ensure
body { width: 720pt; height: 405pt; } in CSS
Debug template to add to your script:
// Add this at the start of your script for debugging console.log('=== Debug Info ==='); console.log('Current directory:', __dirname); console.log('SKILL_DIR:', process.env.SKILL_DIR); console.log('html2pptx path:', path.join(process.env.SKILL_DIR, 'scripts', 'html2pptx')); console.log('==================');
Common mistakes to avoid:
require('./scripts/html2pptx')require('D:\\ops-data\\agent-skills\\pptx\\scripts\\html2pptx')require(path.join(process.env.SKILL_DIR, 'scripts', 'html2pptx'))Reference example:
See
for a complete working example with:example-create-presentation.js
When edit slides in an existing PowerPoint presentation, you need to work with the raw Office Open XML (OOXML) format. This involves unpacking the .pptx file, editing the XML content, and repacking it.
ooxml.md (~500 lines) completely from start to finish. NEVER set any range limits when reading this file. Read the full file content for detailed guidance on OOXML structure and editing workflows before any presentation editing.python ooxml/scripts/unpack.py <office_file> <output_dir>ppt/slides/slide{N}.xml and related files)python ooxml/scripts/validate.py <dir> --original <file>python ooxml/scripts/pack.py <input_directory> <office_file>When you need to create a presentation that follows an existing template's design, you'll need to duplicate and re-arrange template slides before then replacing placeholder context.
Extract template text AND create visual thumbnail grid:
python -m markitdown template.pptx > template-content.mdtemplate-content.md: Read the entire file to understand the contents of the template presentation. NEVER set any range limits when reading this file.python scripts/thumbnail.py template.pptxAnalyze template and save inventory to a file:
template-inventory.md containing:
# Template Inventory Analysis **Total Slides: [count]** **IMPORTANT: Slides are 0-indexed (first slide = 0, last slide = count-1)** ## [Category Name] - Slide 0: [Layout code if available] - Description/purpose - Slide 1: [Layout code] - Description/purpose - Slide 2: [Layout code] - Description/purpose [... EVERY slide must be listed individually with its index ...]
Create presentation outline based on template inventory:
outline.md with content AND template mapping that leverages available designs# Template slides to use (0-based indexing) # WARNING: Verify indices are within range! Template with 73 slides has indices 0-72 # Mapping: slide numbers from outline -> template slide indices template_mapping = [ 0, # Use slide 0 (Title/Cover) 34, # Use slide 34 (B1: Title and body) 34, # Use slide 34 again (duplicate for second B1) 50, # Use slide 50 (E1: Quote) 54, # Use slide 54 (F2: Closing + Text) ]
Duplicate, reorder, and delete slides using
:rearrange.py
scripts/rearrange.py script to create a new presentation with slides in the desired order:
python scripts/rearrange.py template.pptx working.pptx 0,34,34,50,52
Extract ALL text using the
script:inventory.py
Run inventory extraction:
python scripts/inventory.py working.pptx text-inventory.json
Read text-inventory.json: Read the entire text-inventory.json file to understand all shapes and their properties. NEVER set any range limits when reading this file.
The inventory JSON structure:
{ "slide-0": { "shape-0": { "placeholder_type": "TITLE", // or null for non-placeholders "left": 1.5, // position in inches "top": 2.0, "width": 7.5, "height": 1.2, "paragraphs": [ { "text": "Paragraph text", // Optional properties (only included when non-default): "bullet": true, // explicit bullet detected "level": 0, // only included when bullet is true "alignment": "CENTER", // CENTER, RIGHT (not LEFT) "space_before": 10.0, // space before paragraph in points "space_after": 6.0, // space after paragraph in points "line_spacing": 22.4, // line spacing in points "font_name": "Arial", // from first run "font_size": 14.0, // in points "bold": true, "italic": false, "underline": false, "color": "FF0000" // RGB color } ] } } }
Key features:
default_font_size in points extracted from layout placeholders (when available)bullet: true, level is always included (even if 0)space_before, space_after, and line_spacing in points (only included when set)color for RGB (e.g., "FF0000"), theme_color for theme colors (e.g., "DARK_1")Generate replacement text and save the data to a JSON file Based on the text inventory from the previous step:
alignment property on when "bullet": true"bold": true"bullet": true, "level": 0 (level is required when bullet is true)"alignment": "CENTER" for centered text)"font_size": 14.0, "font_name": "Lora")"color": "FF0000" for RGB or "theme_color": "DARK_1" for theme colorsreplacement-text.jsonExample paragraphs field showing proper formatting:
"paragraphs": [ { "text": "New presentation title text", "alignment": "CENTER", "bold": true }, { "text": "Section Header", "bold": true }, { "text": "First bullet point without bullet symbol", "bullet": true, "level": 0 }, { "text": "Red colored text", "color": "FF0000" }, { "text": "Theme colored text", "theme_color": "DARK_1" }, { "text": "Regular paragraph text without special formatting" } ]
Shapes not listed in the replacement JSON are automatically cleared:
{ "slide-0": { "shape-0": { "paragraphs": [...] // This shape gets new text } // shape-1 and shape-2 from inventory will be cleared automatically } }
Common formatting patterns for presentations:
"bullet": true, "level": 0Apply replacements using the
scriptreplace.py
python scripts/replace.py working.pptx replacement-text.json output.pptx
The script will:
Example validation errors:
ERROR: Invalid shapes in replacement JSON: - Shape 'shape-99' not found on 'slide-0'. Available shapes: shape-0, shape-1, shape-4 - Slide 'slide-999' not found in inventory
ERROR: Replacement text made overflow worse in these shapes: - slide-0/shape-2: overflow worsened by 1.25" (was 0.00", now 1.25")
To create visual thumbnail grids of PowerPoint slides for quick analysis and reference:
python scripts/thumbnail.py template.pptx [output_prefix]
Features:
thumbnails.jpg (or thumbnails-1.jpg, thumbnails-2.jpg, etc. for large decks)python scripts/thumbnail.py template.pptx my-grid
workspace/my-grid)--cols 4 (range: 3-6, affects slides per grid)Use cases:
Examples:
# Basic usage python scripts/thumbnail.py presentation.pptx # Combine options: custom name, columns python scripts/thumbnail.py template.pptx analysis --cols 4
To visually analyze PowerPoint slides, convert them to images using a two-step process:
Convert PPTX to PDF:
soffice --headless --convert-to pdf template.pptx
Convert PDF pages to JPEG images:
pdftoppm -jpeg -r 150 template.pdf slide
This creates files like
slide-1.jpg, slide-2.jpg, etc.
Options:
-r 150: Sets resolution to 150 DPI (adjust for quality/size balance)-jpeg: Output JPEG format (use -png for PNG if preferred)-f N: First page to convert (e.g., -f 2 starts from page 2)-l N: Last page to convert (e.g., -l 5 stops at page 5)slide: Prefix for output filesExample for specific range:
pdftoppm -jpeg -r 150 -f 2 -l 5 template.pdf slide # Converts only pages 2-5
IMPORTANT: When generating code for PPTX operations:
Required dependencies (should already be installed):
pip install "markitdown[pptx]" (for text extraction from presentations)npm install -g pptxgenjs (for creating presentations via html2pptx)npm install -g playwright (for HTML rendering in html2pptx)npm install -g react-icons react react-dom (for icons)npm install -g sharp (for SVG rasterization and image processing)sudo apt-get install libreoffice (for PDF conversion)sudo apt-get install poppler-utils (for pdftoppm to convert PDF to images)pip install defusedxml (for secure XML parsing)