Skip to main content

Overview

SlideNotesView is a client component that displays speaker notes synchronized with the presenter’s deck. It polls a sync endpoint to track the current slide and provides manual navigation for demo notes beyond the slide count.
This is a 'use client' component.

Props

notes
(string | null)[]
required
Speaker notes array. Indices 0…slides-1 match slides; extras are demo notes that can be advanced manually.
syncEndpoint
string
required
API endpoint created with the sync route handlers (e.g., /api/nxs-sync).
pollInterval
number
default:"500"
Polling interval in milliseconds. Defaults to 500ms.

Usage Example

Create a notes page

// app/notes/page.tsx
import fs from 'fs';
import path from 'path';
import { parseSpeakerNotes, SlideNotesView } from 'nextjs-slides';

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

export default function NotesPage() {
  return <SlideNotesView notes={notes} syncEndpoint="/api/nxs-sync" />;
}

Custom poll interval

<SlideNotesView 
  notes={notes} 
  syncEndpoint="/api/nxs-sync"
  pollInterval={1000}
/>

Behavior

Sync Mode

  • Polls the syncEndpoint at the specified interval
  • Automatically updates to match the presenter’s current slide
  • Displays a green connection indicator when synced
  • Shows “Slide X / Total” counter

Demo Notes Mode

  • Notes beyond the slide count are treated as “demo notes”
  • User can manually navigate with Prev/Next buttons
  • Displays “Demo X / Total” counter
  • Manual override prevents auto-sync until returning to slide range

No Notes

  • Displays “No notes for this slide.” when notes[index] is null

Sync Endpoint Format

The endpoint should return JSON with:
{
  slide: number,  // Current slide number (1-based)
  total: number   // Total number of slides
}

UI Features

  • Header: Slide/demo counter + connection status indicator
  • Main area: Large, readable note text (responsive font size)
  • Footer: Prev/Next navigation buttons
  • Mobile-optimized: Uses 100dvh, large tap targets, and optimized typography
  • Dark theme: Pre-styled with dark background and high-contrast text

Connection Indicator

  • Green dot: Successfully connected and syncing
  • Red dot: Connection failed or endpoint unreachable

Manual Override

When the user manually navigates to demo notes:
  • Sets manualOverride.current = true
  • Prevents auto-sync from overriding the manual position
  • Reset when returning to slide range via sync

Example: Complete Setup

// app/notes/page.tsx
import fs from 'fs';
import path from 'path';
import { parseSpeakerNotes, SlideNotesView } from 'nextjs-slides';

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

const notes = parseSpeakerNotes(markdown, { stripLeadingTitle: true });

export default function NotesPage() {
  return (
    <SlideNotesView 
      notes={notes} 
      syncEndpoint="/api/nxs-sync"
      pollInterval={500}
    />
  );
}

Notes Format

The notes array should be generated using parseSpeakerNotes:
const notes = parseSpeakerNotes(markdown, { stripLeadingTitle: true });
Each note should be plain text or null. Markdown is not rendered; notes are displayed as-is with pre-wrap whitespace handling.

Build docs developers (and LLMs) love