Skip to content
pptx logo

PPTX Skill

pptx

Use this skill any time a .pptx file is involved — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading or extracting text from .pptx files; editing or updating existing presentations; combining or splitting slide files; working with templates, la...

SKILL.md

Full skill instructions

PPTX Skill

Quick Reference

TaskApproach
Read/​analyze contentpython3 -m markitdown presentation.pptx
Generate structured presentationUse generate_report.js — see below
Create custom from scratchUse pptxgenjs directly (see pptxgenjs section)

Generating Presentations (Recommended)

For structured presentations with cover slide, auto-generated TOC, content slides, and closing, use the pre-built template:

Step 1: Copy the generator script

cp /​builtin-skills/​pptx/​scripts/​generate_report.js ./​generate_pptx.js

Step 2: Build slides_data.json via Python script

Two phases: write slide content files, then assemble into JSON.

CRITICAL: NEVER write or edit .json files directly. Use a Python script with json.dump() to guarantee valid JSON output.

Phase 1 — Write each slide's content as a plain text file using write_file:

For each major topic, read_file the relevant research data, then write_file the slide content directly:

read_file("research_data/​literature.md")           # refresh data in context
write_file("slides/​slide_01_intro.txt", "...")      # write slide body
write_file("slides/​slide_02_analysis.txt", "...")   # next slide
...

Each content slide body should be concise but substantive (3-6 bullet points or 2-4 sentences with specific data and citations).

NEVER write a Python script that contains slide text as string literals. The slide content goes directly into .txt files via write_file, not into Python code.

Language (CRITICAL):

  • All presentation content (title, subtitle, slide headings, body text, chart labels, speaker notes) MUST be written in the user's configured language as specified in the system prompt's ## Language section.
  • If the user's language is Chinese (zh), write the entire presentation in Chinese; if English (en), write in English. Do NOT mix languages unless quoting a proper noun or technical term that has no standard translation.

Phase 2 — Assemble into JSON using a standard assembler script:

import json, glob, os

SLIDES_DIR = "slides"
TITLE = "Presentation Title"
SUBTITLE = "Subtitle or tagline"

# Slide config: (file_pattern, type, title, extra_fields_or_None)
SLIDE_MAP = [
    ("slide_01_*.txt", "section", "Introduction", None),
    ("slide_02_*.txt", "bullets", "Key Findings", None),
    ("slide_03_*.txt", "content", "Market Overview", {"layout": "text-image", "image": "chart.png"}),
    ("slide_04_*.txt", "stat", "Key Metrics", {
        "stats": [
            {"value": "25%", "label": "Revenue Growth"},
            {"value": "15%", "label": "Cost Reduction"},
            {"value": "32%", "label": "Market Share"},
        ]
    }),
    ("slide_05_*.txt", "content", "Trend Analysis", None),
    (None, "chart_pie", "Distribution", {
        "labels": ["Type A", "Type B", "Type C", "Other"],
        "values": [35, 30, 20, 15],
    }),
    (None, "chart_line", "Yearly Trends", {
        "x_labels": ["2020", "2021", "2022", "2023", "2024"],
        "series": [{"name": "Metric", "values": [40, 55, 62, 70, 78]}],
    }),
]

data = {
    "title": TITLE, "subtitle": SUBTITLE,
    "author": "ScienceClaw", "date": "2026-03-09",
    "theme": "midnight", "toc": True, "slides": [],
}

for entry in SLIDE_MAP:
    pattern, stype, title, extra = entry
    slide = {"type": stype, "title": title}

    if pattern:
        matches = sorted(glob.glob(os.path.join(SLIDES_DIR, pattern)))
        if matches:
            body = open(matches[0], encoding="utf-8").read().strip()
            if stype == "bullets":
                slide["items"] = [line.strip() for line in body.split("\n") if line.strip()]
            else:
                slide["body"] = body

    if extra:
        slide.update(extra)
    data["slides"].append(slide)

# Closing slide
data["slides"].append({"type": "closing", "title": "Thank You", "subtitle": "Questions?"})

with open("slides_data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)
print(f"Generated slides_data.json ({len(data['slides'])} slides)")

Step 3: Generate the PPTX

python3 build_slides_data.py   # outputs slides_data.json
node generate_pptx.js slides_data.json output.pptx

Supported slide types

TypeRequired FieldsOptional Fields
title(auto from top-level)title, subtitle, author, date
agendaitems (string array)title (default: "Agenda")
sectiontitlesubtitle
contenttitlebody, layout, image
bulletstitle, itemssubtitle
two_columntitle, left, righteach column: {heading, body} or {heading, items}
tabletitle, headers, rowscaption
stattitle, statsstats: [{value, label}] (2-4 items)
imagetitle, imagecaption
chart_bartitle, categories, seriesseries: [{name, values}]
chart_pietitle, labels, values—
chart_linetitle, x_labels, seriesseries: [{name, values}]
quotetextauthor, title
closingtitlesubtitle, contact

Chart types for data visualization (use 2-4 per presentation, mix types):

  • chart_bar — for comparisons, rankings (e.g. drug efficacy scores)
  • chart_pie — for proportions, distributions (e.g. mutation type breakdown)
  • chart_line — for trends over time (e.g. yearly incidence rates)

Top-level JSON keys

KeyRequiredDescription
titleYesPresentation title (cover slide)
subtitleNoSubtitle on cover slide
authorNoAuthor name
dateNoDate string
themeNoColor theme (see below)
tocNoAuto-generate Table of Contents slide (default: true)
slidesYesArray of slide objects

Available themes

ThemePrimarySecondaryAccentStyle
midnight1E2761CADCFC408EC6Dark navy, professional
forest2C5F2D97BC62F5F5F5Green, nature
coralF96167F9E7952F3C7EWarm, energetic
ocean065A821C729321295CDeep blue, calm
charcoal36454FF2F2F2212121Minimal, modern
teal02809000A89602C39AFresh, trustworthy
berry6D2E46A26769ECE2D0Elegant, warm

Design guidelines

  • Every slide needs a visual element — avoid text-only slides
  • Vary layouts — don't repeat the same layout across slides
  • Use section slides to separate major topics — these also populate the auto-generated TOC
  • Use stat slides for key numbers (big number + label format)
  • Mix chart types — aim for 2-4 charts per presentation (bar for comparisons, pie for distributions, line for trends)
  • Keep bullet points concise — 3-6 items per slide, 1-2 lines each
  • Content quality: Each slide body should contain specific data, not vague summaries. Include numbers, percentages, dates, and source references where possible.

Writing guidelines for long presentations

  1. Use the two-phase workflow: Write slide content as separate text files first, then assemble into JSON. This avoids context loss and allows iterative refinement.
  2. Be specific: Slide bodies should contain concrete data, not generic statements. "Revenue grew 25% to $4.2B in Q3 2025" beats "Revenue increased significantly".
  3. Use section slides as dividers: They auto-populate the TOC and give the audience clear navigation.
  4. Balance text and visuals: For every 2-3 text/​bullet slides, include a chart, stat, or image slide.
  5. End with a closing slide: Include contact info or next steps.
  6. No page/​slide count on cover: Do NOT include total page count or slide count on the cover slide or subtitle — the count is unknown at assembly time and produces inaccurate information.

Reading Content

python3 -m markitdown presentation.pptx

Creating Custom Presentations (pptxgenjs)

For fully custom presentations beyond the template's capabilities, use pptxgenjs directly:

const pptxgen = require("pptxgenjs");
let pres = new pptxgen();
pres.layout = "LAYOUT_16x9";

let slide = pres.addSlide();
slide.addText("Hello World!", { x: 0.5, y: 0.5, fontSize: 36, color: "363636" });

pres.writeFile({ fileName: "output.pptx" });

Key rules for pptxgenjs

  • NEVER use "#" with hex colors — color: "FF0000" not color: "#FF0000"
  • Use bullet: true — NEVER unicode symbols like "•"
  • Use breakLine: true between array items for multi-line text
  • NEVER reuse option objects — pptxgenjs mutates them in-place; create fresh objects each time
  • Coordinates are in inches; LAYOUT_16x9 = 10" × 5.625"

Converting to Images (for QA)

python3 /​builtin-skills/​pptx/​scripts/​office/​soffice.py --headless --convert-to pdf output.pptx
pdftoppm -jpeg -r 150 output.pdf slide

Dependencies

  • npm install -g pptxgenjs — creating presentations
  • pip install "markitdown[pptx]" — text extraction
  • pip install Pillow — image processing
  • LibreOffice (soffice) — PDF conversion
  • Poppler (pdftoppm) — PDF to images