Presnly logoPresnly

API Reference

Complete reference for the presnly.js library: the reference implementation of the Presnly Presentation Protocol.

Presnly Class

The main entry point. Create an instance, configure it, and call .connect().

Presnly class APItypescript
import { Presnly } from 'presnly'

const ppp = new Presnly({
  // Adapter: 'auto' | 'reveal' | 'slidev' | 'vanilla' | PPPAdapter
  adapter: 'auto',

  // Opt into specific capability groups (default: all supported)
  capabilities: ['navigation.jump', 'content.notes'],

  // WebSocket config (for remote control scenarios)
  websocket: {
    url: 'wss://example.com/ppp',
    reconnect: true,
    reconnectInterval: 3000,
  },

  // Lifecycle callbacks
  onConnect: () => console.log('Connected'),
  onDisconnect: () => console.log('Disconnected'),
  onError: (err) => console.error(err),
})

// Start listening for controllers
ppp.connect()

// Properties (read-only)
ppp.adapterName    // string | null: detected adapter name
ppp.capabilities   // PPPCapabilities: negotiated capabilities
ppp.isConnected    // boolean: PPP initialized and transport active

// Disconnect
ppp.disconnect()

PPPAdapter Interface

Implement this interface to add PPP support for any presentation framework. Only detect(), getSlideCount(), getCurrentSlide(), goto(), next(), previous(), and onSlideChange() are required.

PPPAdapter interfacetypescript
interface PPPAdapter {
  readonly name: string

  // Detection
  detect(): boolean

  // Navigation (required)
  getSlideCount(): number
  getCurrentSlide(): number
  goto(slide: number): void
  next(): void
  previous(): void

  // Optional capabilities
  getNotes?(slide: number): string | null
  getSections?(): PPPSection[]
  getMetadata?(): { title?: string; author?: string; date?: string }

  // Event subscription
  onSlideChange(callback: (event: PPPSlideChangeEvent) => void): () => void
}

Writing a Custom Adapter

To support a framework that doesn't have a built-in adapter, implement PPPAdapter and pass it as the adapter option:

Custom adapter exampletypescript
import { Presnly, type PPPAdapter, type PPPSlideChangeEvent } from 'presnly'

class MyFrameworkAdapter implements PPPAdapter {
  readonly name = 'my-framework'

  detect(): boolean {
    return typeof window.MyFramework !== 'undefined'
  }

  getSlideCount(): number {
    return window.MyFramework.slides.length
  }

  getCurrentSlide(): number {
    return window.MyFramework.currentIndex + 1  // PPP is 1-based
  }

  goto(slide: number): void {
    window.MyFramework.navigateTo(slide - 1)    // Framework is 0-based
  }

  next(): void {
    window.MyFramework.next()
  }

  previous(): void {
    window.MyFramework.previous()
  }

  getNotes(slide: number): string | null {
    return window.MyFramework.slides[slide - 1]?.notes ?? null
  }

  onSlideChange(callback: (event: PPPSlideChangeEvent) => void): () => void {
    const handler = () => {
      callback({
        slide: this.getCurrentSlide(),
        total: this.getSlideCount(),
      })
    }
    window.MyFramework.on('change', handler)
    return () => window.MyFramework.off('change', handler)
  }
}

// Use your custom adapter
new Presnly({ adapter: new MyFrameworkAdapter() }).connect()

Type Definitions

Key typestypescript
// Slide state reported in responses and notifications
interface PPPSlideState {
  slide: number       // Current slide (1-based)
  total: number       // Total slides
  isPlaying?: boolean
  section?: string
  fragment?: number
  fragmentTotal?: number
}

// Section structure
interface PPPSection {
  id: string          // Unique section identifier
  title: string       // Human-readable section name
  slideStart: number  // First slide in section (1-based)
  slideEnd: number    // Last slide in section (1-based)
}

// Capabilities declared during initialization
interface PPPCapabilities {
  "navigation.jump"?: boolean
  "navigation.sections"?: boolean
  lifecycle?: boolean
  display?: { blackout?: boolean; whiteout?: boolean; overview?: boolean } | boolean
  "content.notes"?: boolean
  "content.thumbnails"?: boolean
  "content.metadata"?: boolean
  pointer?: boolean
  annotations?: boolean
  timer?: boolean
}

// Slide change event
interface PPPSlideChangeEvent {
  slide: number
  total: number
  section?: string
  fragment?: number
  fragmentTotal?: number
}

Built-in Adapters

AdapterImportDetectsNotes
RevealAdapterpresnlywindow.RevealSupports notes, sections, fragments
SlidevAdapterpresnlywindow.__slidevSupports sections via headings
VanillaAdapterpresnly[data-ppp-slide] elementsSupports notes, sections via data attributes