Generates a self-contained single-file HTML presenter view with embedded slides, navigation, and a three-tab notes panel. Pure Python — no external dependencies. Use when: "presenter view", "presentation mode", "build presenter", "present the slides", "speaker view", "practice mode"
Builds a self-contained single-file HTML presenter view that embeds all slide content directly, with keyboard navigation and a three-tab notes panel. The output file can be opened in any browser — no server, no dependencies, no network connection required.
The presenter view is a single .html file containing:
All slide content — each slide's HTML is embedded in a <section> element
with display: none toggled by JavaScript. Same rendering as source slides,
not screenshots.
Three-tab notes panel — slides in from the right edge when activated:
notes.json tab3_field, default "References")Navigation controls — bottom bar with slide counter, prev/next buttons, and keyboard shortcut hints.
All CSS inlined — no external stylesheets. Slide styles are scoped per section to prevent conflicts.
| Key | Action |
|---|---|
| Right Arrow / Space / Enter | Next slide |
| Left Arrow / Backspace | Previous slide |
| N | Toggle notes panel |
| F | Toggle fullscreen |
| Home | First slide |
| End | Last slide |
| Escape | Exit fullscreen / close notes panel |
| 1 / 2 / 3 | Switch notes tab (when panel is open) |
localStorage — reopening the panel restores the
last active tabnotes.json at build time and embedded in the
HTML as a JavaScript objectnotes.json is missing, the notes panel is omitted entirely (no empty panel)Slides are embedded as full HTML, not images. This preserves:
Each slide is wrapped in a container that enforces 16:9 aspect ratio (1280x720 logical pixels) and scales to fit the browser window via CSS transform.
┌─────────────────────────────────────────────────────────┐
│ │
│ ┌─────────────────────────────────┐ ┌────────────┐ │
│ │ │ │ Notes │ │
│ │ Slide Content │ │ Tab 1 | 2 │ │
│ │ (16:9 scaled) │ │ │ │
│ │ │ │ Walk the │ │
│ │ │ │ audience │ │
│ │ │ │ through... │ │
│ └─────────────────────────────────┘ └────────────┘ │
│ │
│ ◄ Slide 3 of 12 ► [N]otes [F]ullscreen │
└─────────────────────────────────────────────────────────┘
| File | Required | Description |
|---|---|---|
| Slide HTML files | Yes | Individual .html files in --slides-dir |
notes.json | No | Speaker notes from the notes skill |
| Slide manifest | No | slides.json or file list for ordering |
The script determines slide order by:
slides.json manifest if it exists (explicit order)--subset flag to include only specific slide numbersEach slide's CSS is scoped to prevent cross-slide style bleed:
.slide-N)scripts/build_presenter_html.py — pure Python stdlib. No Chrome, no Pillow,
no third-party packages.
# Build presenter view from slides directory
python ${CLAUDE_SKILL_DIR}/scripts/build_presenter_html.py \
--slides-dir ./slides \
--output presenter.html
# Include speaker notes
python ${CLAUDE_SKILL_DIR}/scripts/build_presenter_html.py \
--slides-dir ./slides \
--notes-json notes.json \
--output presenter.html
# Subset of slides (e.g., for a shortened version)
python ${CLAUDE_SKILL_DIR}/scripts/build_presenter_html.py \
--slides-dir ./slides \
--notes-json notes.json \
--subset 1,2,3,7,8,12 \
--output presenter-short.html
| Skill | What | Why |
|---|---|---|
| generate | HTML slide files | Slide content to embed |
| notes | notes.json | Three-tab notes panel content |
| workflow | deck-state.json | Template name for tab3 label |
| outline | outline.json | Slide ordering and section breaks |
| Skill | What | Why |
|---|---|---|
| convert | N/A — presenter view is a delivery artifact | End of pipeline |
| checkpoint | Build status | Session state tracking |
notes.json does not exist, suggest running
the notes skill before building the presenter view.file:// protocol. Do not suggest
running a local server.