spec-driven-presentation-maker works with any .pptx file as a template.
It automatically analyzes the template's layouts, colors, fonts, and placeholders — no manual configuration needed.
Beyond templates, three other resource types can be customized per-user:
- Templates (
.pptx) — slide masters - Styles (
.html) — design guides used by the agent - Assets (images such as
.svg,.png) — icons, logos, illustrations - Config (
config.json) — output directory, extra asset sources, etc.
All four support user-local placement so your customizations survive
pip install --upgrade or a repository re-clone.
When you call analyze_template, the engine inspects the .pptx file and extracts:
- Slide layouts — Name, dimensions, placeholder positions and sizes
- Theme colors — Background, accent colors, text colors
- Fonts — Heading and body fonts
- Placeholders — Title, body, footer with exact coordinates
The agent uses this information to place elements precisely within the template's design system.
HTML decks (deck.json outputFormat: "html") use the same .pptx templates. The engine
converts a template into a theme.css (canvas size, theme colors, fonts, placeholder
positions and text styles), a template.json (layouts, placeholders, slide-number and footer
chrome) and one SVG per layout for the decorations the master and layouts draw (logos,
bands, background art). The result is cached by the template's content hash under
sdpm/.cache/template-html/, so editing the .pptx triggers a fresh conversion. Rendering
the decorations needs LibreOffice and poppler; without them the structure still converts
and the build reports the missing tools once. A template that draws nothing besides its
placeholders (such as the bundled blank-light / blank-dark) never needs them.
Design your template in PowerPoint, Google Slides, or Keynote (export as .pptx):
-
Define slide layouts — At minimum, create:
- A title slide layout
- A content slide layout (title placeholder + body area)
- A section divider layout (optional)
- A blank layout (for custom designs)
-
Set theme colors — Define your brand colors in the slide master's color theme. The agent reads these and uses them consistently.
-
Set fonts — Define heading and body fonts in the slide master. The agent extracts these automatically.
-
Keep it clean — Remove sample content from layouts. The agent works with placeholder positions, not sample text.
-
Add layout instructions via speaker notes — Write usage instructions in the speaker notes of each layout's sample slide. The agent reads these when analyzing the template and follows them when building slides with that layout.
Examples:
- "Use this layout for two-column comparisons"
- "Place images on the right side only"
- "Title should be kept to one line"
- Use descriptive layout names (e.g., "Content with Image", "Two Column") — the agent reads these names
- Ensure background-to-text color contrast ratio of at least 4.5:1
- Test your template by running
analyze_templateand reviewing the output
Any slide size works — 16:9, 4:3, 16:10, and other ratios are all supported. The engine derives the drawing canvas from your template's actual dimensions.
The coordinate system is 1920 px wide, with height following the aspect ratio:
| Template slide size | Canvas in slide JSON |
|---|---|
| 16:9 (13.33 × 7.5 in) | 1920 × 1080 px |
| 4:3 (10 × 7.5 in) | 1920 × 1440 px |
| 16:10 | 1920 × 1200 px |
analyze_template reports the canvas size as slide_size, and the agent records
it in deck.json as slideSize so that slide composition uses the full canvas.
Known limitations for non-16:9 templates:
- Architecture diagram boxes — fixed in #285. Box auto-height is now
calibrated using
slideSize.ptPerPx(the pt-to-px conversion rate reported byanalyze_templateand stored indeck.json). Explicitbox.heightis still accepted for manual fine-tuning. - Style demos — the bundled style gallery HTML files use a fixed 16:9 canvas. This does not affect generated slides (only the design tokens are consumed).
- Deck list thumbnails — the Web UI deck list crops thumbnails to a fixed ratio so that card heights stay aligned in the grid. Slide previews (workspace, carousel) follow the real aspect ratio.
# List all layouts
uv run python3 scripts/pptx_builder.py analyze_template my-template.pptx
# Show specific layout details
uv run python3 scripts/pptx_builder.py analyze_template my-template.pptx --layout "Content"The agent calls analyze_template automatically during the design phase. You can also ask directly:
"Analyze the template and show me the available layouts"
Templates are stored in S3 (DynamoDB caches their metadata). The agent calls list_templates to see available templates, then analyze_template with the selected template ID.
Place your .pptx file anywhere accessible and specify the path when initializing:
{
"tool": "init_deck_workspace",
"arguments": {
"name": "My Deck"
}
}Or simply tell the agent: "Use my-template.pptx for this presentation."
Place templates in <user-config>/templates/ (see User-local templates below) to have
them appear in list_templates automatically. sdpm/templates/ holds the bundled ones; in
an installed SDPM it is part of ~/.sdpm/checkout, which sdpm update manages, so keep your
own templates out of it.
Included sample templates:
sdpm/templates/
├── blank-dark.pptx
└── blank-light.pptx
Custom templates can also be placed outside the package, so they survive a
pip install --upgrade or a re-clone of the repository. Kiro CLI / pptx_builder.py
searches the following locations in order and merges the results in
list_templates:
- Directories listed in
$SDPM_TEMPLATES_DIR(platform path separator::on Unix,;on Windows — same semantics asPATH) <user-config>/templates/— see User-local directory layout belowsdpm/templates/(package-bundled)
A user-local template shadows a bundled one with the same file name, which makes it easy to override sample templates without editing the repository.
The user-local base directory is platform-aware:
| Platform | Location |
|---|---|
| macOS / Linux | $XDG_CONFIG_HOME/sdpm/ (default: ~/.config/sdpm/) |
| Windows | %APPDATA%/sdpm/ (default: C:\Users\<you>\AppData\Roaming\sdpm\) |
Layout:
<user-config>/sdpm/
├── templates/ # User-local .pptx templates
├── styles/ # User-local style HTMLs (see "Custom Styles" below)
├── assets/ # User-local asset sources (see "Custom Assets" below)
│ └── my-company/
│ ├── manifest.json
│ └── logo.svg
└── config.json # Per-user config overrides (output_dir, extra_sources, …)
None of these paths exist by default — create only what you need
(mkdir -p ~/.config/sdpm/styles etc.).
Upload the template to S3 and register it in DynamoDB:
uv run python scripts/upload_template.py \
--file my-template.pptx \
--name "Corporate 2026" \
--bucket <ResourceBucketName> \
--table <TableName>| Parameter | Required | Description |
|---|---|---|
--file |
✅ | Path to the .pptx template file |
--name |
✅ | Display name for the template |
--bucket |
✅ | S3 bucket name (CDK output ResourceBucketName) |
--table |
✅ | Amazon DynamoDB table name (CDK output TableName) |
The script handles S3 upload, template analysis, and Amazon DynamoDB metadata registration automatically.
In the cloud Web UI, each user can add a private note to builtin and user templates from the Templates page. The agent considers these notes—including intended use cases, preferences, and default-use requests—when proposing or selecting a template.
A style is one HTML file that serves as rulebook, reference and gallery sample at once: its
:root tokens (colours, --fs-* font sizes, geometry) are machine-read by apply_style and
the build-time lint, and its slides are a short deck built in the style, about the style: its rules, how titles and
chapters are shaped, and one slide per recurring pattern (comparison, process, table, chart…),
each commented with the regions and components it is built from. What the gallery shows is
what a deck in that style looks like. Composers read the whole file
as specs/art-direction.html, and the orchestrator reads its Message & Outline part before
writing the outline, so a style shapes the deck's structure, not only its look. The skeleton
and token contract are defined in the style workflow (returned by start_style()).
Bundled styles come in two tiers, plus two styles written for Japanese decks. The orthodox tier is for when you do not want to think about looks: any subject, any audience, light or dark. The concept tier is chosen by look — each style commits to one visual idea and states how far it may be pushed. Purpose-specific structure (how a lesson or a workshop deck is organised) belongs to the outline, not the style, so any concept style can carry any kind of deck.
Orthodox — pick one of these when in doubt
| Style | Built for | Look |
|---|---|---|
report |
Documents read alone; numbers, tables and findings first | White, serif findings, one deep-green accent, tables and small multiples, greyscale-safe |
briefing |
Decks spoken to a room, re-read afterwards | Dark, one teal accent, noun-phrase titles with a topic sentence, header bands and rules instead of cards |
aws-dark / aws-light |
Decks about AWS services, architectures and cost — talks/demos (dark) or documents/print (light) | Squid Ink or white ground, official service-category colours for identification, official icons, one Smile Orange emphasis |
Concept — choose by look
| Style | Idea | Look |
|---|---|---|
neo-brutalist |
Blunt hierarchy over polish; "zero apology" | Cream ground, 6px black borders, hard 12px offset shadows, flat primary fills, uppercase labels, square corners |
typographic |
Type is the image; one beat per slide | White, display type at 384px that bleeds off the left edge, focus stacks in black and light grey, one red word or number at most, no shapes or rules at all |
signal |
Warning-sign vocabulary; one thing is highlighted | Near-black, one safety-yellow panel per slide, upright ultra-bold headlines, huge numerals, monospaced metadata, one hazard stripe |
racing |
Momentum; every slide hands off to the next | Near-black, italic condensed headlines, blue-violet-red top stripe, thin white speed lines, one red element |
bento |
One fact per tile; modular product-story rhythm | Soft grey ground, white rounded tiles (20px) on a 24px grid, exactly one dark tile and at most one blue accent tile per slide, faint shadow |
newspaper |
Broadsheet; the deck is meant to be read | Aged paper, near-black serif headlines, 3px masthead rule and 1px hairlines, 2–3 justified columns, drop cap, one red figure or rule |
swiss-poster |
One red geometric shape anchors the page | White, black type at poster sizes that never bleeds, exactly one red circle / bar / band / square (may bleed), 1–2 grid lines, a vertical label |
duotone |
One hard edge, two fields: claim on one, evidence on the other | Near-black and vivid orange, 50/50 or 33/67 split (vertical or horizontal); near-black type on orange, white and orange type on near-black, grey only for meta; shape bar charts with one white bar |
agent-spectrum |
Made to be watched (screen recordings, animated previews, README stills); colour only tells the parts of a figure apart | Flat near-black ground, light type, five builder colours (blue, teal, violet, amber, pink) always in that order, a five-segment stripe on every slide, monospaced labels and tags, dashed region frames; no gradients, glow or shadows |
prism-dark |
The gradient is a pointer: it marks the one thing the title is talking about, everything else is flat | Near-black ground, one violet-to-pink gradient used as gradient text on the key figure, a 4px outline + one filled pill on the chosen card, or one gradient bar; a 40px gradient bar down the left edge is the only constant. No gradient panels, no blur or glow |
prism-light |
Same rule set as prism-dark for lit rooms and print |
White ground, near-black type, flat white cards with 1px borders, the same violet-to-pink gradient in the same pointer roles |
aws-console |
The deck is an AWS Management Console screen; every piece of chrome carries deck information | Two dark header bands (aws wordmark, search box showing the deck title and slide index, notification badge = open actions, date and presenter where region and account sit; a favourites row of numbered section chips with the current section lit) over a white toolbar; page title with an Info link and an outline + orange button pair; white 2px-bordered containers with drag handle, Info, kebab and resize handle; blue links and blue metrics; three fixed status colours; dense 56px rows, no prose |
Japanese — sample text and title grammar in Japanese
| Style | Built for | Look |
|---|---|---|
gradient-card |
Technical walkthroughs on a shared screen, where the listener follows one item at a time | Black ground, rules, bands, round icon nodes and connectors; a thin blue-to-violet gradient on lines and node rims; outlines only around things with a boundary, one magenta outline for the subject; noun-phrase titles with a lead sentence |
mono-blue |
Internal and customer briefings shown once, then read alone as the reference copy | White ground, monotone ink, dark-slate numbered markers and outlined cards, sentence titles ending in です/ます, a grey takeaway band on every slide, exactly one blue outline or pale-blue zone |
Use the style workflow (agent-driven) to generate a new style HTML.
The workflow writes to <user-config>/styles/{name}.html — i.e.
~/.config/sdpm/styles/ on macOS/Linux or %APPDATA%/sdpm/styles/ on Windows.
You can also copy an existing style manually:
mkdir -p ~/.config/sdpm/styles
cp sdpm/references/examples/styles/report.html \
~/.config/sdpm/styles/my-style.htmlSearch order (first match wins on same file name):
- Directories listed in
$SDPM_STYLES_DIR(platform path separator, likePATH) <user-config>/styles/sdpm/references/examples/styles/(package-bundled samples)
list_styles (the MCP tool and the CLI command) scans all three locations and
returns them in a single list; in a client that shows MCP Apps, the tool's result
appears as a style gallery in the chat. User-local styles
shadow bundled ones of the same name so you can override samples without
touching the repository.
spec-driven-presentation-maker includes download scripts for two icon sets:
# AWS Architecture Icons
uv run python3 scripts/download_aws_icons.py
# Material Symbols (Google)
uv run python3 scripts/download_material_icons.pyIcons are stored in sdpm/assets/ with a manifest.json per source:
sdpm/assets/
├── config.json # Optional: user settings (gitignored, see config.example.json)
├── config.example.json # Example config (git-managed)
├── aws/
│ ├── manifest.json # {"icons": [{"name": "Lambda", "file": "Lambda.svg", "tags": [...]}]}
│ └── *.svg
└── material/
├── manifest.json
└── *.svg
{
"type": "image",
"src": "assets:aws/Lambda",
"x": 100, "y": 200, "width": 64, "height": 64
}Reference formats:
assets:{source}/{name}— From a specific source (e.g.,assets:aws/Lambda)icons:{name}— Search all sources (backward compatible)
There are two ways to add a custom asset source (e.g. your company logos):
Place the source directory under the user-local assets path. It is automatically scanned at runtime — no config changes required:
~/.config/sdpm/assets/my-company/ # (Windows: %APPDATA%/sdpm/assets/my-company/)
├── manifest.json
└── logo.svg
manifest.json follows the built-in format:
{
"source": "my-company",
"icons": [
{"name": "my-logo", "file": "logo.svg", "tags": ["brand", "logo"], "type": "service"}
]
}Reference in slides.json:
{ "type": "image", "src": "assets:my-company/logo", "x": 100, "y": 200, "width": 64, "height": 64 }Use this when the files live anywhere on disk (e.g. a shared network drive), or when you want to point at an existing directory without moving it:
{
"extra_sources": [
{
"source": "mybrand",
"manifest": "/path/to/my-icons/manifest.json",
"files_dir": "/path/to/my-icons/"
}
]
}Save as <user-config>/config.json (see User config below).
When an asset name appears in multiple sources, the earlier source wins:
extra_sourcesfromconfig.json— explicit override<user-config>/assets/— auto-discovered user-local sourcessdpm/assets/— built-in sources (aws, material)- Legacy
icons/directory (only if present)
This lets extra_sources override user-local sources, which in turn override
bundled ones. Registering a built-in name in extra_sources is an intentional
way to replace a bundled icon with your own.
Per-user configuration lives in <user-config>/config.json (that is,
~/.config/sdpm/config.json on macOS/Linux or %APPDATA%/sdpm/config.json
on Windows). The file is optional; missing keys fall back to defaults.
Full schema with defaults:
{
"output_dir": "~/Documents/SDPM-Presentations",
"extra_sources": []
}output_dir— Deck root: where the CLI and the MCP servers write decks and generated PPTX files, and where the Local Web UI lists them. Supports~expansion; empty means the default.$SDPM_DECK_ROOT, then$SDPM_OUTPUT_DIR, override it.extra_sources— Additional asset manifests (see Option B above).
The previously-shipped sdpm/assets/config.json is no longer read — it was
lost on pip install --upgrade and is replaced entirely by the user-local
path above.
uv run python scripts/upload_assets.py \
--dir ./my-icons/ \
--bucket <ResourceBucketName> \
--category icons- Getting Started — Install and use SDPM
- Developer guide — CDK deployment, including the template upload step
- Architecture — How the asset resolver works