md-slides — Markdown deck → single-file HTML presentation

Converts a markdown deck (slides separated by `---` HR boundaries or by `# ` H1 headings, with optional `<!-- notes: ...

How to use it

Claude Code
  1. Run the line below. It pulls the whole folder into ~/.claude/skills/md-slides, including the files SKILL.md points to.
  2. Describe your job in plain words. Claude Code follows the skill from there.
Claude Code — installs the whole folder, not just SKILL.md
npx degit alirezarezvani/claude-skills/markdown-html/skills/md-slides#main ~/.claude/skills/md-slides

For one project only, change the path to .claude/skills/md-slides. This skill also uses config_loader.py, slide_splitter.py, presenter_notes_parser.py, deck_html_renderer.py, Prism.js, reveal.js — copying SKILL.md alone won't be enough. See the folder on GitHub.

Claude (web or desktop app)
  1. On this page open ⋯ → Download .md.
  2. Save it as SKILL.md in a folder, zip the folder, then Customize → Skills → + → Create skill → Upload a skill.
  3. Pick the file and Save. Claude shows the name and description and runs a security scan.
  4. Check the skill is switched on.
  5. Start a new chat and describe your job in plain words. The AI follows the skill from there.
ChatGPT or another app
  1. ChatGPT: make a Project and paste it into Instructions.
  2. Neither? Paste it at the top of a new chat — it works for that chat.
Not working?
  • Check which app you pasted it into — the steps above name the right one.
  • Some skills need the paid tier of Claude or ChatGPT.
Step-by-step guide with screenshots · Ask in the forum

Paste into Claude, ChatGPT or Cursor.

Source of md-slides — Markdown deck → single-file HTML presentation

Show the full text103 lines
namedescriptionversionauthorlicensetagscompatible_tools
md-slidesConverts a markdown deck (slides separated by `---` HR boundaries or by `# ` H1 headings, with optional `<!-- notes: ... -->` presenter notes blocks) into a single-file HTML presentation with arrow-key / space / PgDn / PgUp / Home / End / P / Esc keyboard navigation, presenter mode (split view with current slide + speaker notes + clock + next-slide preview), URL-hash deep linking, and `@media print` page-per-slide for PDF export. Triggers when the markdown-html-orchestrator classifies an input as SLIDES, or when invoked directly via /cs:md-slides. Reuses md-document's markdown parser for slide-body rendering and reads design-system tokens via config_loader.py. Refuses if input has no clear slide boundaries, produces a 1-slide deck, or `--strict-notes` is on with < 50% notes coverage. Use after orchestrator routing.2.10.3Alireza RezvaniMIT[markdown, html, slides, deck, presenter-mode, keyboard-nav, print-to-pdf, single-file, design-system][claude-code, codex-cli, cursor, antigravity, opencode, gemini-cli]

md-slides — Markdown deck → single-file HTML presentation

The slide-deck converter. Reads a markdown deck (HR or H1 boundaries, optional presenter notes), emits a single-file HTML presentation that runs in any browser with keyboard navigation, presenter mode, and print-to-PDF.

Three stdlib tools pipeline together:

slide_splitter.py  →  presenter_notes_parser.py  →  deck_html_renderer.py
   (md → ordered      (extract <!-- notes:         (slides + design-system
    slides with       --> blocks, attach            tokens → single-file
    titles)           per slide)                    HTML with keyboard nav)

When to invoke

Symptom Action
markdown-html-orchestrator routes input as SLIDES Invoke this skill
User runs /cs:md-slides <path>.md directly Invoke this skill
Input has 3+ --- HR lines OR 5+ H1 headings with short bodies Invoke this skill
Input is a long-form spec Route to md-document instead
Input is a code review Route to md-review instead
Input has no clear slide boundaries Refuse, route to md-document
Input would produce 1 slide Refuse (it's a poster)

Pipeline

# 1. Split slides on --- or H1 (auto-detect by default)
python3 markdown-html/skills/md-slides/scripts/slide_splitter.py \
    --input <path>.md --output /tmp/slides.json

# 2. Extract <!-- notes: ... --> blocks from each slide
python3 markdown-html/skills/md-slides/scripts/presenter_notes_parser.py \
    --slides /tmp/slides.json --output /tmp/deck.json

# 3. Render single-file HTML deck
python3 markdown-html/skills/md-slides/scripts/deck_html_renderer.py \
    --slides /tmp/deck.json --title "My Talk" --output deck.html

What ships in the HTML

  • All slides as <section class="slide"> — one visible at a time, controlled by JS
  • Keyboard nav — → / Space / PgDn advance; ← / PgUp previous; Home/End jump; P presenter mode; Esc exits presenter
  • URL-hash deep linking — #3 jumps to slide 3; browser back/forward walks slides; share deck.html#5 to send someone directly there
  • Progress bar — 3px at top showing position through the deck
  • Slide counter — bottom-right ("3 / 12")
  • Presenter mode (P key) — splits the window: current slide on left (60% width), panel on right with clock + speaker notes + next-slide preview
  • Print stylesheet — Cmd+P produces a PDF with one slide per page
  • @media (prefers-reduced-motion: reduce) honored
  • 12 brand CSS custom properties from design-system; design_style affects layout density
  • Reuses md-document's markdown parser — slide bodies render with consistent paragraph/list/code/table/callout handling

Hard rules

  1. Refuses input with no clear slide boundaries. Auto mode needs ≥ 3 HR lines or ≥ 5 H1 headings. Otherwise exit 6 — route to md-document.
  2. Refuses 1-slide decks. That's a poster, not a deck. Exit 5.
  3. Refuses input < 100 lines. Same Shihipar threshold as all converters.
  4. Refuses without onboarding. Same gate as every converter.
  5. --strict-notes refuses < 50% notes coverage. A deck where most slides have no notes isn't set up for presenter mode. Exit 7.
  6. Soft-warns slides > 40 source lines. Signal-to-noise; renders anyway but surfaces the count.
  7. Single-file output. All CSS + JS inline. Only external is Google Fonts CSS. Prism.js is opt-in via --syntax.
  8. No JS framework runtime. Vanilla JS + keyboard event handlers, no React/Vue/Svelte.

Forcing-question library (Matt Pocock grill discipline)

  1. Is this actually a deck, or a long document? Recommended: if you can't draw clear slide boundaries, it's not a deck. Canon: Tufte Cognitive Style of PowerPoint.
  2. HR (---) or H1 boundaries? Recommended: HR for typical decks; H1 for outline-driven decks. Canon: Marp / reveal.js / pandoc convergence.
  3. Will it be presented live or distributed for self-paced reading? Recommended: live → need presenter notes; self-paced → notes optional. Canon: Weinschenk 100 Things Every Presenter Needs to Know.
  4. Is there any slide over 40 source lines? Recommended: split it. Canon: NN/g — audience attention drops past ~6 bullets / 200 words.
  5. Is --syntax needed? Recommended: only for decks with substantial code blocks. Default off. Canon: single-file shareability discipline.

Distinct from

  • md-document — that's one continuous document. This is N discrete slides.
  • md-review — that renders diff hunks + annotations. This renders prose slides.
  • marketing/landing/ — that's a landing page, not a deck.
  • Keynote / PowerPoint — those are graphic-design tools. This is for markdown-authored decks projected from a browser.

Output artifact

{default_output_dir}/deck-{slug}.html (path resolved by orchestrator's output_path_resolver.py; collision suffix -2, -3, … by default).

References

  • Shihipar — Claude Code HTML output (Medium, 2026), Tier 3 use case "Slide Decks"
  • Reynolds — Presentation Zen (less is more discipline)
  • Atkinson — Beyond Bullet Points (the bullet-heavy failure mode)
  • Tufte — The Cognitive Style of PowerPoint (the polemic)
  • reveal.js / Big / Marp — convergent markdown-to-deck conventions
  • See references/ for full citations (presentation_ux, keyboard_nav_patterns, single_file_deck_conventions)
1---
2name: md-slides
3description: "Converts a markdown deck (slides separated by `---` HR boundaries or by `# ` H1 headings, with optional `<!-- notes: ... -->` presenter notes blocks) into a single-file HTML presentation with arrow-key / space / PgDn / PgUp / Home / End / P / Esc keyboard navigation, presenter mode (split view with current slide + speaker notes + clock + next-slide preview), URL-hash deep linking, and `@media print` page-per-slide for PDF export. Triggers when the markdown-html-orchestrator classifies an input as SLIDES, or when invoked directly via /cs:md-slides. Reuses md-document's markdown parser for slide-body rendering and reads design-system tokens via config_loader.py. Refuses if input has no clear slide boundaries, produces a 1-slide deck, or `--strict-notes` is on with < 50% notes coverage. Use after orchestrator routing."
4version: 2.10.3
5author: Alireza Rezvani
6license: MIT
7tags: [markdown, html, slides, deck, presenter-mode, keyboard-nav, print-to-pdf, single-file, design-system]
8compatible_tools: [claude-code, codex-cli, cursor, antigravity, opencode, gemini-cli]
9---
10 
11# md-slides — Markdown deck → single-file HTML presentation
12 
13The slide-deck converter. Reads a markdown deck (HR or H1 boundaries, optional presenter notes), emits a single-file HTML presentation that runs in any browser with keyboard navigation, presenter mode, and print-to-PDF.
14 
15Three stdlib tools pipeline together:
16 
17```
18slide_splitter.py → presenter_notes_parser.py → deck_html_renderer.py
19 (md → ordered (extract <!-- notes: (slides + design-system
20 slides with --> blocks, attach tokens → single-file
21 titles) per slide) HTML with keyboard nav)
22```
23 
24## When to invoke
25 
26| Symptom | Action |
27|---|---|
28| `markdown-html-orchestrator` routes input as SLIDES | Invoke this skill |
29| User runs `/cs:md-slides <path>.md` directly | Invoke this skill |
30| Input has 3+ `---` HR lines OR 5+ H1 headings with short bodies | Invoke this skill |
31| Input is a long-form spec | Route to `md-document` instead |
32| Input is a code review | Route to `md-review` instead |
33| Input has no clear slide boundaries | Refuse, route to `md-document` |
34| Input would produce 1 slide | Refuse (it's a poster) |
35 
36## Pipeline
37 
38```bash
39# 1. Split slides on --- or H1 (auto-detect by default)
40python3 markdown-html/skills/md-slides/scripts/slide_splitter.py \
41 --input <path>.md --output /tmp/slides.json
42 
43# 2. Extract <!-- notes: ... --> blocks from each slide
44python3 markdown-html/skills/md-slides/scripts/presenter_notes_parser.py \
45 --slides /tmp/slides.json --output /tmp/deck.json
46 
47# 3. Render single-file HTML deck
48python3 markdown-html/skills/md-slides/scripts/deck_html_renderer.py \
49 --slides /tmp/deck.json --title "My Talk" --output deck.html
50```
51 
52## What ships in the HTML
53 
54- **All slides as `<section class="slide">`** — one visible at a time, controlled by JS
55- **Keyboard nav** — `→` / `Space` / `PgDn` advance; `←` / `PgUp` previous; `Home`/`End` jump; `P` presenter mode; `Esc` exits presenter
56- **URL-hash deep linking** — `#3` jumps to slide 3; browser back/forward walks slides; share `deck.html#5` to send someone directly there
57- **Progress bar** — 3px at top showing position through the deck
58- **Slide counter** — bottom-right ("3 / 12")
59- **Presenter mode** (P key) — splits the window: current slide on left (60% width), panel on right with clock + speaker notes + next-slide preview
60- **Print stylesheet** — `Cmd+P` produces a PDF with one slide per page
61- **`@media (prefers-reduced-motion: reduce)`** honored
62- **12 brand CSS custom properties** from design-system; design_style affects layout density
63- **Reuses md-document's markdown parser** — slide bodies render with consistent paragraph/list/code/table/callout handling
64 
65## Hard rules
66 
671. **Refuses input with no clear slide boundaries.** Auto mode needs ≥ 3 HR lines or ≥ 5 H1 headings. Otherwise exit 6 — route to md-document.
682. **Refuses 1-slide decks.** That's a poster, not a deck. Exit 5.
693. **Refuses input < 100 lines.** Same Shihipar threshold as all converters.
704. **Refuses without onboarding.** Same gate as every converter.
715. **`--strict-notes` refuses < 50% notes coverage.** A deck where most slides have no notes isn't set up for presenter mode. Exit 7.
726. **Soft-warns slides > 40 source lines.** Signal-to-noise; renders anyway but surfaces the count.
737. **Single-file output.** All CSS + JS inline. Only external is Google Fonts CSS. Prism.js is opt-in via `--syntax`.
748. **No JS framework runtime.** Vanilla JS + keyboard event handlers, no React/Vue/Svelte.
75 
76## Forcing-question library (Matt Pocock grill discipline)
77 
781. **Is this actually a deck, or a long document?** Recommended: if you can't draw clear slide boundaries, it's not a deck. Canon: Tufte *Cognitive Style of PowerPoint*.
792. **HR (`---`) or H1 boundaries?** Recommended: HR for typical decks; H1 for outline-driven decks. Canon: Marp / reveal.js / pandoc convergence.
803. **Will it be presented live or distributed for self-paced reading?** Recommended: live → need presenter notes; self-paced → notes optional. Canon: Weinschenk *100 Things Every Presenter Needs to Know*.
814. **Is there any slide over 40 source lines?** Recommended: split it. Canon: NN/g — audience attention drops past ~6 bullets / 200 words.
825. **Is `--syntax` needed?** Recommended: only for decks with substantial code blocks. Default off. Canon: single-file shareability discipline.
83 
84## Distinct from
85 
86- **`md-document`** — that's one continuous document. This is N discrete slides.
87- **`md-review`** — that renders diff hunks + annotations. This renders prose slides.
88- **`marketing/landing/`** — that's a landing page, not a deck.
89- **Keynote / PowerPoint** — those are graphic-design tools. This is for markdown-authored decks projected from a browser.
90 
91## Output artifact
92 
93`{default_output_dir}/deck-{slug}.html` (path resolved by orchestrator's `output_path_resolver.py`; collision suffix `-2`, `-3`, … by default).
94 
95## References
96 
97- Shihipar — *Claude Code HTML output* (Medium, 2026), Tier 3 use case "Slide Decks"
98- Reynolds — *Presentation Zen* (less is more discipline)
99- Atkinson — *Beyond Bullet Points* (the bullet-heavy failure mode)
100- Tufte — *The Cognitive Style of PowerPoint* (the polemic)
101- reveal.js / Big / Marp — convergent markdown-to-deck conventions
102- See `references/` for full citations (presentation_ux, keyboard_nav_patterns, single_file_deck_conventions)
103 

Discussion

Alternatives

Also in Decks & layoutsSee all 106 in Design →