From bilardi
Use when adding/modifying slide types, extending build_slides.py / extract_slides.py / config.py, swapping or adapting a .pptx template, scaffolding a new workshop project from existing templates, or debugging mismatches between template and script. Also use when the user mentions "md-to-slides", "build_slides", "type:N slide", or "slides_it.md".
How this skill is triggered — by the user, by Claude, or both
Slash command
/bilardi:md-to-slidesThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Build workshop `.pptx` decks from a Markdown source via a custom Python script that clones template slides and replaces text / lists / code / tables / images based on the MD content.
Build workshop .pptx decks from a Markdown source via a custom Python script that clones template slides and replaces text / lists / code / tables / images based on the MD content.
scripts/ : current snapshot of build_slides.py, extract_slides.py, config.py, README.md. Copy into a workshop folder when scaffolding a new project.templates/python_workshop_template.pptx : reference template (8 template slides + 2 BLANK markers + 4 footer slides). Copy and rename to python_workshop.pptx in the workshop folder.<workshop_dir>/
build_slides.py # main: MD -> .pptx
extract_slides.py # one-shot: .pptx -> MD bootstrap
config.py # type-to-template map, fonts, colors, keywords
README.md # user-facing docs
python_workshop.pptx # actual deck
slides_it.md # source content (per language)
images/ # assets used by type:7 slides
The .pptx must guarantee, otherwise the script fails or produces wrong output:
config.TYPE_TO_TEMPLATE):
BLANK + BG, manual content)BIG_NUMBER + BG; updated in-place from MD type:2)TITLE + BG)TITLE_AND_BODY; left bullet list, right Solarized code box)TITLE, no BG)TITLE_AND_BODY; both Solarized code boxes)TITLE_ONLY_1)TITLE_ONLY_1 with table shape)BLANK slides, one right after the templates, one right before the footer. The script clears and rebuilds everything strictly between them.placeholder_format.idx == 0#002B36 (Solarized base03)layout.name == "BLANK" and no text in any shape| Task | What to edit |
|---|---|
| New slide type N | template at slide N + config.TYPE_TO_TEMPLATE + apply_content case (if custom) + README.md |
New MD section name (e.g. ### caption) | parse_md + relevant apply_content branch |
| Change font size globally | config.TEXT_PT |
| Change Solarized palette | config.SOLAR_* |
| Add Python keyword | config.PY_KEYWORDS / PY_BUILTINS |
| Translate to another language | new slides_<lang>.md + new .pptx with translated templates 1-2 (cover, agenda) + run build_slides.py --md slides_<lang>.md --pptx <output>.pptx |
| Adopt new template same schema | swap the .pptx, no config change |
| Adopt new template different positions | edit config.TYPE_TO_TEMPLATE |
.pptx (typical position: right before the start marker)N: position to config.TYPE_TO_TEMPLATE (and shift AGENDA_POSITION if you inserted before slide 2)### subtitle/### left/### right/### image/### table), add a if typ == N: block in apply_contentparse_md to recognize itREADME.md MD format section with an examplemkdir -p <workshop_dir>
cd <workshop_dir>
# copy script files from this skill
cp <skill_dir>/scripts/* .
cp <skill_dir>/templates/python_workshop_template.pptx python_workshop.pptx
# write content
$EDITOR slides_it.md
# build
uv run python build_slides.py
For uv: the workshop dir needs pyproject.toml with python-pptx, pillow (used by replace_picture):
[project]
name = "workshop-<name>"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["python-pptx>=1.0.0", "pillow>=10.0.0"]
Then uv sync once.
slides_it.mdis_code_box detection; if needed, update the hardcoded "002B36" in is_code_box in build_slides.py## type:N in MD without N in config.TYPE_TO_TEMPLATE (except type:2, special-cased for in-place agenda) : the slide is silently skipped (warning to stderr only)build_slides.py after deep manual edits : the rebuild discards them. Keep the MD as the source of truthWhen 2+ templates exist with different conventions (positions, layouts, marker styles), consider:
config.py constants into a per-template config file (e.g. templates/<name>/config.py)--template <name> CLI flag to build_slides.py that loads the right configconfig.py has one set of constants; this is fine for 1 templateCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub bilardi/publish-claude-plugins --plugin bilardi