| name | md-to-pptx |
| description | Build executive-ready PowerPoint decks (.pptx) programmatically with a consistent visual language — navy header, red accent, banded footer — for research findings, status reviews, and stakeholder briefings |
| lastReviewed | 2026-07-23T00:00:00.000Z |
Md To Pptx
Composable Python primitives for building on-brand executive decks from Python — no template shopping, no manual box-nudging in PowerPoint.
Purpose-built for turning a manuscript, plan/PROJECT_STATUS.md, or a set of findings into a 10-slide executive-review deck in one command. Ships as a small set of reusable helpers (deck_helpers.py) plus a worked example (early_findings.py) that produced Early-Findings.pptx at the repo root.
When to use this
| Situation | Reach for this? |
|---|
| 5–15 slide executive review of a research pipeline or project | Yes |
| Status brief to a stakeholder who won't read the paper | Yes |
| Findings summary alongside a Quarto manuscript | Yes |
Slides where you need version control (git diff on the source) | Yes — Python source is diffable, .pptx is not |
| 40+ slide training deck with lots of authored transitions | No — use PowerPoint directly |
| Real-time collaborative editing | No — this is a one-way build tool |
| One-off ad-hoc slide someone will edit heavily | No — build in PowerPoint |
What you get
- Consistent visual language — navy
#0B2A50 header band + red #C0392B accent + muted grey body + light-grey card fill. Matches the project's manuscript typography.
- 16:9 widescreen (13.333 × 7.5 in) by default.
- Diffable source — every deck lives as a Python file in git. Rebuilding is one command.
- No template dependency — starts from a blank
Presentation(), so no reference .pptx to maintain.
Quick start
1. Install python-pptx
pip install -r .github\skills\local\md-to-pptx\scripts\requirements.txt
2. Rebuild the reference deck
python .github\skills\local\md-to-pptx\examples\early_findings.py
Produces Early-Findings.pptx at the repo root (~50 KB, 10 slides).
3. Build your own
The recommended pattern is to separate content from layout: keep slide
copy in a markdown spec file, and use Python only for rendering. See
examples/early_findings.content.md for a worked example — it declares each
slide's title, bullets, and tables in plain markdown, and
examples/early_findings.py mirrors that content into deck_helpers calls.
The two files are kept in sync by hand. There is deliberately no automated
markdown-to-pptx parser — layout decisions (which slide is a 4-card summary
vs. a 2-column status vs. a hero number) are best made in Python where you
can see the shape math. The content file is authoritative for wording,
sourcing, and the audit trail from paper → deck.
Copy examples/early_findings.py and edit. All the primitives live in scripts/deck_helpers.py:
from pptx.util import Inches
from deck_helpers import (
new_presentation, add_header, add_footer, add_bullets, add_text,
add_rect, NAVY, ACCENT, INK, BG_BAND, WHITE, GOOD, MUTED,
)
prs = new_presentation()
BLANK = prs.slide_layouts[6]
s = prs.slides.add_slide(BLANK)
add_header(s, "Findings", "Two dimensions explain most variance",
slide_width=prs.slide_width)
add_bullets(s, Inches(0.6), Inches(1.8), Inches(12), Inches(4),
["First point", "Second point"], size=16)
add_footer(s, 1, 1, subtitle="Project · Section",
slide_width=prs.slide_width, slide_height=prs.slide_height)
prs.save("my-deck.pptx")
Primitives
| Function | Purpose |
|---|
new_presentation(w=13.333, h=7.5) | 16:9 blank Presentation |
add_rect(slide, x, y, w, h, fill, line=None) | Filled rectangle |
add_text(slide, x, y, w, h, text, size, bold, color, align, font) | Single-run text box |
add_bullets(slide, x, y, w, h, items, size, color, bullet, space_after_pt) | Bulleted list |
add_header(slide, kicker, title, slide_width) | Navy top band + kicker + title + accent rule |
add_footer(slide, page_no, total, subtitle, slide_width, slide_height) | Grey band with page counter |
Palette constants exported: NAVY, INK, MUTED, ACCENT, GOOD, BG_BAND, WHITE.
Slide patterns (from early_findings.py)
| Pattern | Where in example |
|---|
| Title slide with stat cards | Slide 1 |
| Bulleted narrative | Slide 2 |
| Two-column status (answered vs open) | Slide 3 |
| Three-column feature grid | Slide 4 |
| Hero number + supporting cards | Slide 5 |
| Numbered findings with badges | Slide 6 |
| Left-accent-bar callout stack | Slide 7 |
| Side-by-side priority lists | Slide 8 |
| Bullets + reproducibility spec card | Slide 9 |
| Ask + zebra-striped roadmap table | Slide 10 |
Each pattern is 10–40 lines of Python. Copy-paste the pattern you need, adjust content, and go.
Customising the palette
Override the palette constants before you call the helpers:
import deck_helpers
from pptx.dml.color import RGBColor
deck_helpers.NAVY = RGBColor(0x00, 0x2B, 0x5C)
deck_helpers.ACCENT = RGBColor(0xE8, 0x1B, 0x23)
Rendering & distribution
.pptx files open in:
- PowerPoint (desktop + web)
- Google Slides (upload → view/edit)
- LibreOffice Impress
- Keynote (import)
To convert to PDF:
# Windows — via PowerPoint COM
Start-Process powerpnt -ArgumentList '/quiet','/pt','deck.pdf','deck.pptx'
# Or open in PowerPoint and File → Export → PDF
To render slides as PNG for embedding in markdown:
libreoffice --headless --convert-to png deck.pptx
Troubleshooting
| Symptom | Cause | Fix |
|---|
TypeError: add_text() got an unexpected keyword argument 'italic' | You passed italic=True — the primitives don't support it yet | Use a separate add_text(..., bold=True) and set .runs[0].font.italic after |
| Header title overflows the slide | Title too long for 12" width | Break to two lines, or reduce size from 28 to 24 |
| Rectangles have unwanted borders | add_rect called without line=None | Always pass line=None (default) unless you want a border |
| Bullets don't render as bullets in Google Slides | Different bullet-glyph handling | Passing bullet="•" (default) works everywhere |
| Wrong font on Mac | Calibri not installed | Change default via font="Helvetica Neue" in add_text calls |
Related skills
| Skill | Relationship |
|---|
| md-to-word | Same visual identity, .docx target — use for prose-heavy reports |
| md-to-html | Web-viewable HTML with same styling |
| status-reporting | The prose skill; this skill is the delivery vehicle |
Falsifiability
- This skill is wrong if the produced
.pptx fails to open in PowerPoint desktop / web or Google Slides.
- The primitives are wrong if the same code produces visibly different layouts on Windows vs macOS at the same python-pptx version.
- Not earning its keep if every new deck requires hand-editing in PowerPoint after generation — that means the primitives don't cover the patterns actually needed. Extend
deck_helpers.py rather than editing in PowerPoint.