# How PPT Master Generates and Embeds Speaker Notes into PPTX Files

> Discover how PPT Master generates speaker notes from Markdown and embeds them as XML in PPTX files during SVG-to-PPTX conversion. Learn the process now.

- Repository: [HugoHe/ppt-master](https://github.com/hugohe3/ppt-master)
- Tags: internals
- Published: 2026-04-24

---

**PPT Master automatically discovers Markdown files in the `notes/` folder, converts them to plain text, and injects them as XML notes-slides into the final PPTX package during the SVG-to-PPTX conversion process.**

PPT Master (hugohe3/ppt-master) is an open-source automation framework for building presentation decks from SVG assets. When generating output files, the tool handles **speaker notes** by reading optional Markdown documentation and embedding it directly into the Open XML structure, ensuring presenters have contextual annotations available in PowerPoint.

## Discovering Markdown Notes Files

The discovery phase is orchestrated by `pptx_discovery.find_notes_files` in [`skills/ppt-master/scripts/svg_to_pptx/pptx_discovery.py`](https://github.com/hugohe3/ppt-master/blob/main/skills/ppt-master/scripts/svg_to_pptx/pptx_discovery.py). This function scans the `project/notes/*.md` path and constructs a dictionary mapping SVG file stems to their corresponding notes content.

### Filename-Based and Index-Based Matching

The system supports two strategies to pair notes with slides:

- **Filename-based matching** (preferred): A notes file named [`01_cover.md`](https://github.com/hugohe3/ppt-master/blob/main/01_cover.md) automatically pairs with `01_cover.svg` based on identical stem names.
- **Index-based matching** (legacy fallback): Files named [`slide01.md`](https://github.com/hugohe3/ppt-master/blob/main/slide01.md) or [`slide_1.md`](https://github.com/hugohe3/ppt-master/blob/main/slide_1.md) map to the first SVG in the sequence.

The implementation uses regex to detect index patterns while prioritizing exact stem matches:

```python

# skills/ppt-master/scripts/svg_to_pptx/pptx_discovery.py

def find_notes_files(project_path: Path, svg_files: list[Path] | None = None) -> dict[str, str]:
    ...
    for notes_file in notes_dir.glob('*.md'):
        stem = notes_file.stem
        # Index-based match

        match = re.search(r'slide[_]?(\d+)', stem)
        ...
        # Filename-based match (overrides index-based)

        if stem in svg_stems_mapping:
            notes[stem] = content

```

The CLI entry point in [`pptx_cli.py`](https://github.com/hugohe3/ppt-master/blob/main/pptx_cli.py) controls this behavior via the `--no-notes` flag:

```python
enable_notes = not args.no_notes
notes: dict[str, str] = {}
if enable_notes:
    notes = find_notes_files(project_path, svg_files)

```

## Converting Markdown Syntax to Plain Text

Once discovered, raw Markdown content must be sanitized for the PPTX format. The `pptx_notes.markdown_to_plain_text` function in [`skills/ppt-master/scripts/svg_to_pptx/pptx_notes.py`](https://github.com/hugohe3/ppt-master/blob/main/skills/ppt-master/scripts/svg_to_pptx/pptx_notes.py) strips formatting syntax—converting headings, bold markers, and list bullets into clean plain text while collapsing empty lines.

```python

# skills/ppt-master/scripts/svg_to_pptx/pptx_notes.py

def markdown_to_plain_text(md_content: str) -> str:
    ...
    for line in md_content.split('\n'):
        if line.startswith('#'):
            text = re.sub(r'^#+\s*', '', line).strip()
            ...
        elif line.strip().startswith('- '):
            ...
        else:
            ...

```

## Constructing the Notes-Slide XML

PPTX files store speaker notes as separate XML documents linked to their parent slides. PPT Master generates these via two dedicated helpers in [`pptx_notes.py`](https://github.com/hugohe3/ppt-master/blob/main/pptx_notes.py):

- `create_notes_slide_xml(slide_num, notes_text)`: Builds the `<p:notes>` root element containing `<a:p>` paragraphs for each line of text.
- `create_notes_slide_rels_xml(slide_num)`: Generates the relationship file defining connections to the slide master and the corresponding slide.

These functions produce the exact Open XML markup required by the Office Open XML specification.

## Injecting Notes into the PPTX Package

The final assembly occurs inside `pptx_builder.create_pptx_with_native_svg` within [`skills/ppt-master/scripts/svg_to_pptx/pptx_builder.py`](https://github.com/hugohe3/ppt-master/blob/main/skills/ppt-master/scripts/svg_to_pptx/pptx_builder.py). During the per-slide iteration, the system conditionally writes notes files when `enable_notes` is true and content exists for the current SVG stem.

The process creates the necessary directory structure, writes the XML documents, and registers relationships:

```python

# skills/ppt-master/scripts/svg_to_pptx/pptx_builder.py (excerpt)

if enable_notes:
    svg_stem = svg_path.stem
    notes_content = notes.get(svg_stem, '') if notes else ''
    notes_text = markdown_to_plain_text(notes_content) if notes_content else ''
    
    if notes_text:
        notes_slides_dir = extract_dir / 'ppt' / 'notesSlides'
        notes_slides_dir.mkdir(exist_ok=True)

        notes_xml_path = notes_slides_dir / f'notesSlide{slide_num}.xml'
        notes_xml = create_notes_slide_xml(slide_num, notes_text)
        with open(notes_xml_path, 'w', encoding='utf-8') as f:
            f.write(notes_xml)

        notes_rels_dir = notes_slides_dir / '_rels'
        notes_rels_dir.mkdir(exist_ok=True)
        notes_rels_path = notes_rels_dir / f'notesSlide{slide_num}.xml.rels'
        notes_rels_xml = create_notes_slide_rels_xml(slide_num)
        with open(notes_rels_path, 'w', encoding='utf-8') as f:
            f.write(notes_rels_xml)

        _append_relationship(
            rels_path,
            'http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide',
            f'../notesSlides/notesSlide{slide_num}.xml',
        )

```

The `_append_relationship` helper inserts the requisite `<Relationship>` entry into the slide's `.rels` file, establishing the link between the slide and its notes.

## Command-Line Controls

By default, notes processing is enabled. Users can explicitly disable it using the `--no-notes` flag:

```bash
python -m skills.ppt-master.scripts.svg_to_pptx.pptx_cli \
    examples/ppt169_demo \
    -s final \
    --no-notes  # Skip notes discovery and embedding

```

When notes are present and processed, the CLI displays a “+notes” indicator alongside the slide progress output.

## Summary

- PPT Master treats speaker notes as optional Markdown files located in the `notes/` directory.
- The `find_notes_files` function maps note files to SVG slides using filename or index matching.
- `markdown_to_plain_text` sanitizes content by removing Markdown syntax before XML generation.
- Two XML components are created: the notes slide (`<p:notes>`) and its relationship file.
- [`pptx_builder.py`](https://github.com/hugohe3/ppt-master/blob/main/pptx_builder.py) embeds these into the PPTX package under `ppt/notesSlides/` and updates slide relationships.
- Use `--no-notes` to disable the entire pipeline.

## Frequently Asked Questions

### What file format does PPT Master use for speaker notes?

PPT Master expects speaker notes as **Markdown files** (`.md`) stored in the project's `notes/` folder. The content is automatically converted to plain text during the PPTX generation process to ensure compatibility with PowerPoint's native notes format.

### How does PPT Master match notes to specific slides?

The system attempts **filename-based matching** first, pairing [`slide_name.md`](https://github.com/hugohe3/ppt-master/blob/main/slide_name.md) with `slide_name.svg`. If no exact match exists, it falls back to **index-based matching**, interpreting filenames like [`slide01.md`](https://github.com/hugohe3/ppt-master/blob/main/slide01.md) or [`slide_1.md`](https://github.com/hugohe3/ppt-master/blob/main/slide_1.md) as corresponding to the first SVG in the sequence. This logic is implemented in [`pptx_discovery.py`](https://github.com/hugohe3/ppt-master/blob/main/pptx_discovery.py).

### Can I disable speaker notes generation?

Yes. Pass the `--no-notes` flag to the CLI command, or set `enable_notes=False` when calling `create_pptx_with_native_svg` programmatically. When disabled, the system skips discovery, parsing, and XML generation entirely, producing a PPTX file without speaker notes.

### Where are speaker notes stored inside the generated PPTX?

Speaker notes reside in the `ppt/notesSlides/` directory within the PPTX archive (which is a ZIP file). Each slide with notes has a corresponding `notesSlide{number}.xml` file and a `notesSlide{number}.xml.rels` file in the `_rels` subdirectory. You can inspect these by unzipping the `.pptx` file or using command-line tools like `unzip -p output.pptx ppt/notesSlides/notesSlide1.xml`.