Skip to main content

Overview

parseSpeakerNotes parses a markdown string into an array of speaker notes, one per slide. Slides are separated by --- on its own line.

Function Signature

function parseSpeakerNotes(
  markdown: string,
  options?: { stripLeadingTitle?: boolean }
): (string | null)[]

Parameters

markdown
string
required
The markdown content containing speaker notes separated by ---.
options.stripLeadingTitle
boolean
default:"false"
If true, removes a leading section that is a single markdown heading (# Title). Use when the file starts with a document title that shouldn’t be treated as slide notes.

Returns

return
(string | null)[]
Array of speaker notes where indices map to slides: notes[0] = slide 1, notes[1] = slide 2, etc. Empty sections produce null (no notes for that slide).

Markdown Format

Sections are separated by --- on its own line:
Welcome everyone. This is the opening slide.

---

Talk about the base container here.

---

---

Slide 4 notes. Slide 3 had none.

Results

  • Index 0: “Welcome everyone. This is the opening slide.”
  • Index 1: “Talk about the base container here.”
  • Index 2: null (empty section)
  • Index 3: “Slide 4 notes. Slide 3 had none.”

Usage Examples

Basic parsing

import fs from 'fs';
import path from 'path';
import { parseSpeakerNotes } from 'nextjs-slides';

const markdown = fs.readFileSync(
  path.join(process.cwd(), 'app/slides/notes.md'),
  'utf-8'
);

const notes = parseSpeakerNotes(markdown);

Strip leading title

const notes = parseSpeakerNotes(markdown, { stripLeadingTitle: true });
If your notes.md starts with:
# My Presentation

---

First slide notes here.
With stripLeadingTitle: true, the ”# My Presentation” section is removed and “First slide notes here” becomes notes[0].

Use with SlideDeck

import fs from 'fs';
import path from 'path';
import { parseSpeakerNotes, SlideDeck } from 'nextjs-slides';
import { slides } from './slides';

const notes = parseSpeakerNotes(
  fs.readFileSync(path.join(process.cwd(), 'app/slides/notes.md'), 'utf-8'),
  { stripLeadingTitle: true }
);

export default function SlideLayout({ children }: { children: React.ReactNode }) {
  return (
    <SlideDeck
      slides={slides}
      speakerNotes={notes}
      basePath="/slides"
      exitUrl="/"
    >
      {children}
    </SlideDeck>
  );
}

Implementation Details

  • Splits on /^---$/m (regex matches --- on its own line)
  • Trims each section and converts empty strings to null
  • When stripLeadingTitle is true, checks if the first section matches /^#+\s+.+$/ (one or more # followed by text)
  • Empty sections between separators become null

Build docs developers (and LLMs) love