PPT Template Creator This skill creates SKILLS, not presentations. Use this when a user wants to turn their PowerPoint template into a reusable skill that can generate presentations later. If the user just wants to create a presentation, use the pptx skill instead. The generated skill includes: assets/template.pptx - the template file SKILL.md - complete instructions (no reference to this meta skill needed) For general skill-building best practices , refer to the skill-creator skill. This skill focuses on PPT-specific patterns. Workflow User provides template (.pptx or .potx) Analyze template - extract layouts, placeholders, dimensions Initialize skill - use the skill-creator skill to set up the skill structure Add template - copy .pptx to assets/template.pptx Write SKILL.md - follow template below with PPT-specific details Create example - generate sample presentation to validate Package - use the skill-creator skill to package into a .skill file Step 2: Analyze Template CRITICAL: Extract precise placeholder positions - this determines content area boundaries. from pptx import Presentation prs = Presentation ( template_path ) print ( f"Dimensions: { prs . slide_width / 914400 : .2f } \" x { prs . slide_height / 914400 : .2f } \"" ) print ( f"Layouts: { len ( prs . slide_layouts ) } " ) for idx , layout in enumerate ( prs . slide_layouts ) : print ( f"\n[ { idx } ] { layout . name } :" ) for ph in layout . placeholders : try : ph_idx = ph . placeholder_format . idx ph_type = ph . placeholder_format . type
IMPORTANT: Extract exact positions in inches
left
- ph
- .
- left
- /
- 914400
- top
- =
- ph
- .
- top
- /
- 914400
- width
- =
- ph
- .
- width
- /
- 914400
- height
- =
- ph
- .
- height
- /
- 914400
- (
- f" idx=
- {
- ph_idx
- }
- , type=
- {
- ph_type
- }
- "
- )
- (
- f" x=
- {
- left
- :
- .2f
- }
- \", y=
- {
- top
- :
- .2f
- }
- \", w=
- {
- width
- :
- .2f
- }
- \", h=
- {
- height
- :
- .2f
- }
- \""
- )
- except
- :
- pass
- Key measurements to document:
- Title position
-
- Where does the title placeholder sit?
- Subtitle/description
-
- Where is the subtitle line?
- Footer placeholders
-
- Where do footers/sources appear?
- Content area
- The space BETWEEN subtitle and footer is your content area Finding the True Content Start Position CRITICAL: The content area does NOT always start immediately after the subtitle placeholder. Many templates have a visual border, line, or reserved space between the subtitle and content area. Best approach: Look at Layout 2 or similar "content" layouts that have an OBJECT placeholder - this placeholder's y position indicates where content should actually start.
Find the OBJECT placeholder to determine true content start
for idx , layout in enumerate ( prs . slide_layouts ) : for ph in layout . placeholders : try : if ph . placeholder_format . type == 7 :
OBJECT type
top
- ph
- .
- top
- /
- 914400
- (
- f"Layout [
- {
- idx
- }
- ]
- {
- layout
- .
- name
- }
- OBJECT starts at y= { top : .2f } \"" )
This y value is where your content should start!
except : pass Example: A template might have: Subtitle ending at y=1.38" But OBJECT placeholder starting at y=1.90" The gap (0.52") is reserved for a border/line - do not place content there Use the OBJECT placeholder's y position as your content start, not the subtitle's end position. Step 5: Write SKILL.md The generated skill should have this structure: [company]-ppt-template/ ├── SKILL.md └── assets/ └── template.pptx Generated SKILL.md Template The generated SKILL.md must be self-contained with all instructions embedded. Use this template, filling in the bracketed values from your analysis:
name : [ company ] - ppt - template description : [ Company ] PowerPoint template for creating presentations. Use when creating [ Company ] - branded pitch decks , board materials , or client presentations.
[Company] PPT Template
Template:
assets/template.pptx
([WIDTH]" x [HEIGHT]", [N] layouts)
Creating Presentations
python
from
pptx
import
Presentation
prs
=
Presentation
(
"path/to/skill/assets/template.pptx"
)
# DELETE all existing slides first
while
len
(
prs
.
slides
)
>
0
:
rId
=
prs
.
slides
.
_sldIdLst
[
0
]
.
rId
prs
.
part
.
drop_rel
(
rId
)
del
prs
.
slides
.
_sldIdLst
[
0
]
# Add slides from layouts
slide
=
prs
.
slides
.
add_slide
(
prs
.
slide_layouts
[
LAYOUT_IDX
]
)
Key Layouts | Index | Name | Use For | |
|
|
| | [0] | [Layout Name] | [Cover/title slide] | | [N] | [Layout Name] | [Content with bullets] | | [N] | [Layout Name] | [Two-column layout] |
Placeholder Mapping ** CRITICAL: Include exact positions (x, y coordinates) for each placeholder. **
Layout [N]: [Name] | idx | Type | Position | Use | |
|
|
|
| | [idx] | TITLE (1) | y=[Y]" | Slide title | | [idx] | BODY (2) | y=[Y]" | Subtitle/description | | [idx] | BODY (2) | y=[Y]" | Footer | | [idx] | BODY (2) | y=[Y]" | Source/notes |
Content Area Boundaries ** Document the safe content area for custom shapes/tables/charts: **
Content Area (for Layout [N]):
- Left margin: [X]" (content starts here)
- Top: [Y]" (below subtitle placeholder)
- Width: [W]"
- Height: [H]" (ends before footer)
For 4-quadrant layouts:
- Left column: x=[X]", width=[W]"
- Right column: x=[X]", width=[W]"
- Top row: y=[Y]", height=[H]"
- Bottom row: y=[Y]", height=[H]"
** Why this matters: ** Custom content (textboxes, tables, charts) must stay within these boundaries to avoid overlapping with template placeholders like titles, footers, and source lines.
Filling Content ** Do NOT add manual bullet characters ** - slide master handles formatting.
python
# Fill title
for
shape
in
slide
.
shapes
:
if
hasattr
(
shape
,
'placeholder_format'
)
:
if
shape
.
placeholder_format
.
type
==
1
:
# TITLE
shape
.
text
=
"Slide Title"
# Fill content with hierarchy (level 0 = header, level 1 = bullet)
for
shape
in
slide
.
shapes
:
if
hasattr
(
shape
,
'placeholder_format'
)
:
idx
=
shape
.
placeholder_format
.
idx
if
idx
==
[
CONTENT_IDX
]
:
tf
=
shape
.
text_frame
for
para
in
tf
.
paragraphs
:
para
.
clear
(
)
content
=
[
(
"Section Header"
,
0
)
,
(
"First bullet point"
,
1
)
,
(
"Second bullet point"
,
1
)
,
]
tf
.
paragraphs
[
0
]
.
text
=
content
[
0
]
[
0
]
tf
.
paragraphs
[
0
]
.
level
=
content
[
0
]
[
1
]
for
text
,
level
in
content
[
1
:
]
:
p
=
tf
.
add_paragraph
(
)
p
.
text
=
text
p
.
level
=
level
Example: Cover Slide
python
slide
=
prs
.
slides
.
add_slide
(
prs
.
slide_layouts
[
[
COVER_IDX
]
]
)
for
shape
in
slide
.
shapes
:
if
hasattr
(
shape
,
'placeholder_format'
)
:
idx
=
shape
.
placeholder_format
.
idx
if
idx
==
[
TITLE_IDX
]
:
shape
.
text
=
"Company Name"
elif
idx
==
[
SUBTITLE_IDX
]
:
shape
.
text
=
"Presentation Title | Date"
Example: Content Slide
python
slide
=
prs
.
slides
.
add_slide
(
prs
.
slide_layouts
[
[
CONTENT_IDX
]
]
)
for
shape
in
slide
.
shapes
:
if
hasattr
(
shape
,
'placeholder_format'
)
:
ph_type
=
shape
.
placeholder_format
.
type
idx
=
shape
.
placeholder_format
.
idx
if
ph_type
==
1
:
shape
.
text
=
"Executive Summary"
elif
idx
==
[
BODY_IDX
]
:
tf
=
shape
.
text_frame
for
para
in
tf
.
paragraphs
:
para
.
clear
(
)
content
=
[
(
"Key Findings"
,
0
)
,
(
"Revenue grew 40% YoY to $50M"
,
1
)
,
(
"Expanded to 3 new markets"
,
1
)
,
(
"Recommendation"
,
0
)
,
(
"Proceed with strategic initiative"
,
1
)
,
]
tf
.
paragraphs
[
0
]
.
text
=
content
[
0
]
[
0
]
tf
.
paragraphs
[
0
]
.
level
=
content
[
0
]
[
1
]
for
text
,
level
in
content
[
1
:
]
:
p
=
tf
.
add_paragraph
(
)
p
.
text
=
text
p
.
level
=
level
Step 6: Create Example Output Generate a sample presentation to validate the skill works. Save it alongside the skill for reference. PPT-Specific Rules for Generated Skills Template in assets/ - always bundle the .pptx file Self-contained SKILL.md - all instructions embedded, no external references No manual bullets - use paragraph.level for hierarchy Delete slides first - always clear existing slides before adding new ones Document placeholders by idx - placeholder idx values are template-specific