PPTX Skill
Quick Reference
| Task | Approach |
|---|---|
| Read/analyze content | python3 -m markitdown presentation.pptx |
| Generate structured presentation | Use generate_report.js — see below |
| Create custom from scratch | Use 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
bashcp /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
## Languagesection. - 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:
pythonimport 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
bashpython3 build_slides_data.py # outputs slides_data.json node generate_pptx.js slides_data.json output.pptx
Supported slide types
| Type | Required Fields | Optional Fields |
|---|---|---|
title | (auto from top-level) | title, subtitle, author, date |
agenda | items (string array) | title (default: "Agenda") |
section | title | subtitle |
content | title | body, layout, image |
bullets | title, items | subtitle |
two_column | title, left, right | each column: {heading, body} or {heading, items} |
table | title, headers, rows | caption |
stat | title, stats | stats: [{value, label}] (2-4 items) |
image | title, image | caption |
chart_bar | title, categories, series | series: [{name, values}] |
chart_pie | title, labels, values | — |
chart_line | title, x_labels, series | series: [{name, values}] |
quote | text | author, title |
closing | title | subtitle, 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
| Key | Required | Description |
|---|---|---|
title | Yes | Presentation title (cover slide) |
subtitle | No | Subtitle on cover slide |
author | No | Author name |
date | No | Date string |
theme | No | Color theme (see below) |
toc | No | Auto-generate Table of Contents slide (default: true) |
slides | Yes | Array of slide objects |
Available themes
| Theme | Primary | Secondary | Accent | Style |
|---|---|---|---|---|
midnight | 1E2761 | CADCFC | 408EC6 | Dark navy, professional |
forest | 2C5F2D | 97BC62 | F5F5F5 | Green, nature |
coral | F96167 | F9E795 | 2F3C7E | Warm, energetic |
ocean | 065A82 | 1C7293 | 21295C | Deep blue, calm |
charcoal | 36454F | F2F2F2 | 212121 | Minimal, modern |
teal | 028090 | 00A896 | 02C39A | Fresh, trustworthy |
berry | 6D2E46 | A26769 | ECE2D0 | Elegant, 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
- 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.
- Be specific: Slide bodies should contain concrete data, not generic statements. "Revenue grew 25% to $4.2B in Q3 2025" beats "Revenue increased significantly".
- Use section slides as dividers: They auto-populate the TOC and give the audience clear navigation.
- Balance text and visuals: For every 2-3 text/bullet slides, include a chart, stat, or image slide.
- End with a closing slide: Include contact info or next steps.
- 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
bashpython3 -m markitdown presentation.pptx
Creating Custom Presentations (pptxgenjs)
For fully custom presentations beyond the template's capabilities, use pptxgenjs directly:
javascriptconst 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"notcolor: "#FF0000" - Use
bullet: true— NEVER unicode symbols like "•" - Use
breakLine: truebetween 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)
bashpython3 /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 presentationspip install "markitdown[pptx]"— text extractionpip install Pillow— image processing- LibreOffice (
soffice) — PDF conversion - Poppler (
pdftoppm) — PDF to images


