The deck is one .md file; everything else is rendered from it.
The render command
Every render in this skill — previews, the render check, exports — is this command plus its output flags:
npx --yes @marp-team/marp-cli <deck.md> --html --allow-local-files <output flags>
--htmllets inline<svg>and HTML components render. Without it, every chart prints as literal markup text in PDF and PNG output.--allow-local-filesresolves relative image paths.- Output flags:
--images png(one PNG per slide),--pdf,--pptx,--pptx --pptx-editable,-o deck.html. - If it cannot find a browser, set
CHROME_PATHto a Chrome/Chromium binary.
scripts/preview.sh <dir> (Step 2) and scripts/export.sh <deck.md> pdf|pptx|html|all [--editable] (Step 5) wrap this command.
Step 0 — Route
Pick the branch, then follow only its steps:
| Branch | When | Steps |
|---|---|---|
| New | Topic, notes or content to turn into a deck | 1 → 2 → 3 → 4 → 5 |
| Quick | Vague ask ("make it look good"), low stakes, or nobody to answer questions | 1 and 2 without asking: infer the brief, pick the preset from the Quick table, state both in one line → 3 → 4 → 5 |
| Import | A .pptx to rebuild as Markdown |
Import → 1 (content and length come from the file; ask purpose and density) → 2 → 3 → 4 → 5 |
| Edit | An existing Marp .md |
read it; keep its frontmatter, theme and density → 3 on the requested slides only → 4 → 5 |
Step 1 — Brief
Ask these together in one message (a structured-question UI if available):
- Purpose — pitch / board or investor reporting / teaching / conference talk / internal.
- Length — talk duration or slide count. Guide: 5 min ≈ 5–8 slides, 10 min ≈ 10–15, 20 min ≈ 15–25.
- Content — ready / rough notes / topic only. If ready, get it; if they supply images, judge each (usable? subject? dominant colours) and plan the outline around text and images together.
- Density — the deck's governing choice:
- Speaker-led: one idea per slide, large type, 1–3 short lines, statement and quote slides, more slides.
- Reading-first: self-contained slides, grids and tables, 4–8 bullets or 4–6 cards, annotated diagrams.
Done when all four are answered (or, on Quick, inferred and stated back in one line).
Step 2 — Style (show, don't tell)
People recognise a look faster than they can name one, so show rendered options.
- Read
references/themes.md. Pick 3 genuinely different candidates for this brief: one restrained preset, one expressive preset, one wildcard (another preset, or a custom palette block written to the variable contract). High-stakes decks: all three restrained. - Write each as a single-slide Marp file in
.marp-deck/previews/(style-a.md,style-b.md,style-c.md): the real title slide of this deck — its title, subtitle, presenter, date, and the user's logo if given — dressed in that candidate's theme (Base rules + its palette block). Everything on the slide is deck content; preset names belong only in your message. - Render with
bash scripts/preview.sh .marp-deck/previews/, show the PNGs, and ask which one (offer "mix elements").
Done when the user has picked. On Quick, take the first row that matches the audience:
| Audience / content | Preset |
|---|---|
| Finance, corporate, board | Swiss Modern or Electric Studio |
| Data, dashboards, metrics | Dark starter |
| Technical, developer | Terminal Green or Neon Cyber |
| Teaching, editorial, research | Paper & Ink or Notebook Tabs |
| Creative, event, launch | Creative Voltage or Split Pastel |
Import (PPTX branch)
python scripts/extract-pptx.py <input.pptx> <out_dir>→extracted-slides.json+assets/(installpython-pptxif missing).- Show the user each slide's title, content summary and image count; confirm before styling.
- Continue at Step 1. In Step 3, keep all text, slide order, images (as
./assets/...) and speaker notes (as HTML comments).
Step 3 — Generate
Read references/components.md, Base rules and the chosen palette block in references/themes.md, and the one file in examples/ closest to the brief (showcase-components.md when none is closer). That example is the quality bar for composition, spacing and density.
Outline the deck (one line per slide, sized to the Step 1 length), then write it:
- Frontmatter:
marp: true,paginate,sizeif not 16:9, and instyle:the Base rules block followed by the chosen palette block, both verbatim. Logo goes inheader:. - Density from Step 1 governs every slide. A slide that outgrows its density becomes two slides; type size stays put.
- Components earn their place over bullets: a chart instead of a bare number, metric cards, status dots, timelines, mockups. Vary chart types across the deck. Keep every
<div>/<svg>block free of blank lines — a blank line ends the HTML block, and indented lines after it render as a code block. - One style from first slide to last: the palette's fonts, one dominant colour, the accent reserved for data highlights, and the signature classes named in the palette's CSS comments.
- Contrast: the shipped palettes clear the floors in
themes.md→ Variable contract; any colour you change or add is checked against--darkbefore rendering.
Done when every slide in the outline exists in the file.
Step 4 — Render check
Render every slide with --images png and look at every PNG. Fix and re-render until each slide is clean:
- all content sits inside the canvas — nothing cut off at the bottom or right edge (Marp clips overflow without warning);
- every chart and icon draws as a graphic, never as visible
<svg …>text; - no text fades into its background;
- nothing overlaps.
Done when every slide is clean. Delete the PNGs and .marp-deck/previews/.
Step 5 — Deliver
- Report file location, preset (or kept theme), slide count.
- Offer export, with honest trade-offs:
-
PDF — pixel-faithful and static; email and print. Add
--pdf-notesto carry speaker notes,--pdf-outlinesfor bookmarks. -
PPTX — one image per slide, so text is not editable.
--pptx-editablegives real text boxes, needs LibreOffice, and is less faithful to the CSS. -
Editable PPTX without LibreOffice — when
--pptx-editablefails (LibreOffice 24.2+ dropped the Impress HTML import filter), export viaofficecliinstead:# Install officecli (single binary, no Office installation needed): curl -fsSL https://raw.githubusercontent.com/iOfficeAI/OfficeCLI/main/install.sh | bash # Build the editable deck from the same Markdown source: python3 scripts/md2pptx-officecli.py deck.md deck-editable.pptx # or: bash scripts/export.sh deck.md pptx --editable (auto-falls back to officecli)md2pptx-officecli.pyparses the deck structurally — headings, bullets, numbered lists, tables, blockquotes, and simple header-tag rows (<div class="peg-row">-style markup becomes a small square + label) — and writes native text boxes, tables and shapes. It carries the deck's theme colours over from the:rootvariables when present, and uses neutral defaults otherwise. Fidelity is intentionally lower than the Marp render: HTML components and SVG charts become placeholder text. Treat the PDF/HTML export as the visual master and this as the editable companion. -
Full-fidelity editable decks — for house-style decks with signature components (numbered tags, callouts, accent bands), build the PPTX directly with officecli commands (
officecli create,add,batch— seeofficecli help pptx). This is the route used when a brand system must survive into the editable file; it needs a per-deck builder script. -
HTML — the only format that keeps animations,
<details>, and*fragment reveals.
-
- To edit by hand: VS Code with "Marp for VS Code", settings
markdown.marp.enableHtml: trueandmarkdown.marp.allowLocalFiles: true. Colours live in the:root/sectionvariables, fonts in the@import.
Marp syntax reference
The parts that differ from plain Markdown:
- Slides split on
---. Canvas 1280×720 by default;size: 4:3gives 960×720. - Directives: global in frontmatter;
<!-- key: value -->applies from this slide onward; the_prefix (<!-- _class: lead -->,<!-- _paginate: false -->,<!-- _header: '' -->,<!-- _backgroundColor: #111 -->) applies to this slide only. - Slide-only CSS:
<style scoped>…</style>inside the slide. - Fitted headline:
# <!-- fit --> Big statementscales the heading to the slide width — made for speaker-led statement slides. - Fragments:
*bullets (instead of-) reveal one at a time in HTML presentation mode. - Speaker notes: any HTML comment that is not a directive.
- Images:
sizes inline;fills the slide (fit,cover,contain, or80%);splits the slide and leaves the rest for text; several![bg]lines tile side by side, and![bg vertical]on the first stacks them. Filters chain in the same brackets:brightness:0.4 blur:4px grayscale sepia contrast:1.2 saturate:1.5 opacity:0.5. Paths are always relative (./). - Page numbers in CSS:
section::after { content: attr(data-marpit-pagination) ' / ' attr(data-marpit-pagination-total); }. - Full-slide decorations: draw them as extra
backgroundlayers onsection; asection::beforestretched bytop/bottominsets renders at zero height. - Negating a CSS function:
calc(-1 * clamp(...))— a bare-clamp(...)is silently dropped.