ppt — Generate Professional PPTs with Code
Draw PPTs with code, no templates: Reproducible (modify data, rerun the script), git-friendly, coordinates precise to 0.01 inches; no WYSIWYG, rely on Step 4 rendering verification for quality assurance.
Step 1 · Research & Copywriting (No Fabrication)
Answer the three audience questions before writing: Who is the audience (general public / experts / clients)? What do they already know about the project? What three things should they be able to repeat after seeing the deck? Write these answers at the top of the copy draft; all subsequent decisions are governed by them.
Source material must only come from real project data (README / CLAUDE.md / docs / data backends, choose by type). No numbers without a source enter the PPT; facts the audience doesn't need don't go into the body — internal metrics (function count, API constants, internal codenames) are excluded by default; only retain them if the audience is technical.
Dig for content, not just list terms: Collecting numbers and feature names is not research. Tailor the depth to the PPT type — Tech/Product: design decisions + effect comparisons; Portfolio: project details and trade-offs; Data Report: metrics and baselines; Narrative Brand: people, scenes, turning points.
Outline before individual slides: After research, write the narrative outline — one main thread (the whole deck argues one thing) + three opening answers (what it is / who it's for / what problem it solves) + each slide's role in the argument chain (what it builds on from the previous slide, what it sets up for the next). Explain concepts before using them; no forward references. Two consecutive slides that don't connect = reorder. Write the per-slide copy draft (title + key points + speaking script; the speaking script goes into the notes() speaker notes, serving as the copy source for video production workflows and the live presentation script) under the outline. Titles must participate in the progression, not be standalone slogans.
Two-pass drafting: The first pass writes fully — a complete narrative, assuming the audience knows nothing, thoroughly explaining what it is, who it's for, and what it solves; it's okay to be long. The second pass polishes — first use the humanizer to remove artificial phrasing, then trim according to the four rules below. The humanizer is a polisher, not a first-draft template; writing to its standards from the start produces text that is thin and jumpy, shouting slogans without proper explanation.
- No empty statements: Key points must include details (features with design rationale or effects, data with metrics). Delete bare noun lists.
- Numbers need context: Value + metric + composition or comparison, and it must be a number the audience cares about. Numbers without context from research cannot be the main visual.
- Each slide ≥3 traceable, specific facts: Cover the layout and read only the text; it should be "explaining" not "listing".
- Slot rules: Large text slots (cover main title, closing large text, section titles) only use claim sentences or identity statements (with an opinion, sounding like a slogan). Domain names, version numbers, dates, and statistics always go to subtitles or meta-info positions.
Zero tolerance for buzzwords, in two layers: Business clichés (empower, close the loop, matrix, ecosystem, one-stop, end-to-end) are directly deleted; technical jargon (API constants, internal function names, system codenames, implementation details) is filtered by audience — for non-technical audiences, either delete or explain in plain language on the same slide. Numbers over adjectives; titles write opinions not noun phrases; dashes (em dash and en dash) are banned in both Chinese and English. For important projects, show the copy to the user before layout.
Step 2 · Design System (Finalize Before Coding, No Changes Midway)
| Dimension | Rule |
|---|---|
| Color Palette | Extract from the project's design language (README visual section / site primary color / brand VI). If none: use_theme('warm' / 'tech' / 'forest'). 7+1 closed system (7 roles + paper white), no colors added midway; small text to background ≥4.5:1 |
| Grid | 16:9 (13.333 × 7.5 in) · margins 0.55 · page number (12.35, 7.02) · top coral short bar + section label |
| Font Size | 54 cover / 40 large numbers / 30 slide title / 19 card title / 13 body / 11 secondary / 9 notes, no intermediate values allowed |
| Font | Chinese: Microsoft YaHei; Code / domain names / numbers / version numbers: Consolas |
| Density | One argument per slide; split if text exceeds 3 lines, trim rows if table exceeds 6 rows |
Step 3 · Generation
pip install python-pptx -i https://pypi.tuna.tsinghua.edu.cn/simple(first time)- Copy
templates/primitives.py+animate.pyto the target projectscripts/, writegen-<name>-deck.py - Use expressions for coordinates (e.g.,
Inches(0.55 + i * 3.13)), no magic numbers; callcheck_fit()before placing text, split lines/pages if[FIT-WARN]appears
Animations (optional; Windows + MS Office + pywin32). Use auto_deck() by default to handle everything (cover cascade / card float_up / number zoom / link wipe / table rows 0.06s fast cascade / section number wipe up). Manual adjustments only for fine-tuning:
anim = Anim(prs)
anim.auto_deck() # Auto-arrange entire PPT
anim.fx(footer, 'fade', dur=0.4) # Special element touch-up
anim.chart(gf, 'series') # Native chart series wipe in
P.set_transition(prs, 'fade') # Uniform transitions (auto-skip morph pages)
P.auto_show(prs) # Auto-timing via speaking script: auto-play entire deck, screen recording = rough cut
prs.save('deck.pptx')
anim.apply('deck.pptx') # Must be after save; COM write + read-back self-verify
# Fine-tuning: anim.stagger(P.shape_groups(s, 'card'), 'float_up', step=0.12)
# Growth narrative (morph true interpolation, occupies two consecutive pages, auto_show auto-skips; verify: EntryEffect==3954; 2019+, WPS degrades to fade):
P.growth_chart(prs, 6, 'Growth', 'Title', cats, vals, highlight=2) # Bar/column
P.growth_line(prs, 8, 'Trend', 'Title', cats, vals, highlight=5) # Line
P.growth_donut(prs, 10, 'Mix', 'Title', cats, vals) # Donut
Effect word list (COM verified): fade / wipe / appear / float_up / float_down / zoom / grow_turn / ease_in / split / wheel / stretch; 90s gimmicks not accepted. Rhythm > flash: duration 0.40.6s, stagger interval 0.10.2s, ≤2 effects per page, fixed page decorations (top short bar / page number / bottom line) not animated; data charts always use growth_*, native charts only when need to change data in PowerPoint after delivery.
Modifying existing pptx (via script, no manual editing, save to new filename): P.deck_replace(prs, {'Old Name': 'New Name'}) full text replacement (including notes); P.deck_recolor(prs, dict(zip(P.THEMES['warm'].values(), P.THEMES['tech'].values()))) recolor entire deck to another theme.
Page Paradigms (dictionary, not checklist: choose according to Step 1 narrative outline, don't create content just to fill a paradigm; repeating the same paradigm is fine, having 9 different paradigms in one deck is a capability showcase, not a narrative; density comes from Step 1, not from paradigms themselves):
| Paradigm | Function | Usage |
|---|---|---|
| Cover | slide_cover | Opening: large title 54 + right vertical color block |
| Section | slide_section | Navigation for 12+ page decks, magazine style (frame lines + muted number + items) |
| Timeline | slide_timeline | Evolution / roadmap, highlight current position |
| Versus | slide_versus | A/B, before/after comparisons, center VS circle |
| Quote | slide_quote | One sentence worth a full page (for 12+ page decks) |
| Cards | slide_cards | Parallel functions / modules, auto wrap |
| Numbers | slide_numbers | Equal-weight metric overview |
| Media | slide_media | Screenshot + key points; sidebar= large image 60% + callouts + footnotes |
| Dense | slide_dense | Deep dive into a subsystem: main area 60% + sidebar grouped list |
| Table | slide_table | API / model / checklist comparison, 6~9 rows, column width hierarchy |
| Chain | slide_chain | Architecture flow, highlight reverse color + subs cards |
| Rows | slide_rows | Tech stack / configuration |
| Growth | growth_chart / line / donut | Data growth morph true interpolation |
| Native Chart | bar / line / donut_chart | For changing data in PowerPoint after delivery |
| Closing | slide_closing | Contact info; slogan= custom large text (claim sentence) |
Step 4 · Rendering Verification (Mandatory, Cannot Skip)
Three-level pipeline, automation first, manual review only on final output:
① Programmatic Screening: Convert to PDF via Office COM (Presentations.Open then SaveAs("<output>.pdf", 32)) → python <skill_dir>/templates/verify.py <output>.pdf. Check for page overflow, placeholders, WCAG contrast (≥72pt decorative large text exempt). Exit code 1 = problem, modify script and rerun.
② Blind Visual Review: Render PNGs via pymupdf (fitz + get_pixmap(dpi=100)) → Submit to a sub-agent without generation context with two questions: first, check each page for four issues (overflow / garbled text / alignment / contrast); second, audience recall test — give it only the first 1/3 of the pages, ask "What is this, who is it for, what problem does it solve?" — if it can't answer, Step 1's audience definition or opening was wrong, go back and rewrite copy before regenerating. Do not presume exemptions in the blind review prompt (don't say "this is intentional"): report suspect elements like elements cropped by page edges, oversized low-contrast decorative text as potential issues for a fresh eye. If problems found, modify script and rerun; no manual editing of pptx.
Use absolute paths for actual images in visual verification, review against current version or hash; choose compatible paths when encountering tool-specific path limits, don't require directory copying.
③ User Final Review: After the first two levels have cleared mechanical issues, the user only sees the final output.
Step 5 · Delivery
Report: page count + page list / file path and size / three-level verification conclusion / number of speaking script pages / total auto-play duration / generation script location (reproducible). Submit scripts within the git repository (pptx artifacts not tracked in git).
Boundaries & Gotchas
- No MS Office → Step 4 degrades to LibreOffice
soffice --convert-to pdf; if neither available → clearly report "visual verification not performed" - GBK console:
printdisables non-ASCII characters, useOK - pptx native table column width out of control → always use custom-drawn table rows (box + text per row)
- Missing Chinese glyphs → set font to YaHei at run level (handled in primitives)
shape_idper-page independent numbering, not unique globally;animate.pypositions by XML tree; secondary development should not search by ID globally; pywin32:pip install pywin32 -i https://pypi.tuna.tsinghua.edu.cn/simple- docx / xlsx can reuse primitives approach, but page paradigms table only applies to pptx
Current Workflow & Archiving
Content-director handles audience, material sourcing, and narrative draft; PPT targets editable slide deck delivery. Generate after design confirmation; video freeze-frame rules don't apply to PPT. Generation scripts, input data, necessary materials and their hashes are retained with the recipe; delivery manifest declares PPT/PDF/cover; clean up before archive restoration verification only. Visual verification and user final review are reported separately.