How It Works
Phone sync uses a simple polling mechanism:- Presenter deck (laptop): When you navigate with arrow keys or spacebar,
SlideDeckPOSTs the current slide number to the sync endpoint - Sync endpoint: Stores the current slide state in server memory
- Notes viewer (phone): Polls the endpoint every 500ms and displays the corresponding note
notes[slide - 1] displays the note for the current slide.
Sync state lives in server memory. This works perfectly for
next dev or single-server deployments, but won’t persist across serverless function invocations on platforms like Vercel.Setup
Create the sync API route
Export the pre-built handlers from This creates an in-memory sync endpoint that stores
nextjs-slides/sync:app/api/nxs-sync/route.ts
{ slide, total } state.Create the notes page
Use the same
notes.md file and parseSpeakerNotes call to ensure indices match:app/notes/page.tsx
SlideNotesView Component
SlideNotesView is a phone-optimized client component that displays speaker notes:
Props
| Prop | Type | Default | Description |
|---|---|---|---|
notes | (string | null)[] | required | Speaker notes array. Indices 0…slides-1 match slides; extras are demo notes. |
syncEndpoint | string | required | API endpoint created with the sync route handlers. |
pollInterval | number | 500 | Polling interval in milliseconds. |
UI Features
- Header: Shows “Slide X / Y” during presentation, “Demo X / Y” for demo notes
- Connection indicator: Green dot when connected, red when disconnected
- Manual controls: Prev/Next buttons for manual override or demo notes
- Dark theme: Optimized for low-light presentation environments
- Responsive text: Scales from 18px to 28px based on viewport
Sync Endpoint Implementation
The sync endpoint is a simple in-memory store:src/sync.ts
SlideDeck component calls POST when navigating, and SlideNotesView polls GET to stay in sync.
Demo Notes Behavior
When you have extra sections in your notes file beyond the slide count:- During slides: Phone auto-syncs to the current slide
- After last slide: Header changes to “Demo 1 / 2”
- Manual control: Use Prev/Next buttons to step through demo notes
- No auto-sync: Phone stays on the current demo note until you manually advance
Troubleshooting
Notes are out of sync- Ensure
syncEndpointis set on bothSlideDeckandSlideNotesView - Verify both use the same
notes.mdfile and parsing options - Check that your API route is accessible at the specified path
- Verify the sync endpoint is running and accessible
- Check browser console for CORS or network errors
- Ensure phone and laptop are on the same network
- Use
parseSpeakerNotes(markdown, { stripLeadingTitle: true })
- The in-memory store can hit different serverless instances
- For production, implement a shared store (Redis, KV, etc.)