Skip to main content
Run multiple slide decks in the same app with different URLs, fonts, and themes. Use basePath, exitUrl, and className to configure each deck independently.

Basic Setup

Create separate slide layouts for each deck:
app/
  slides/
    layout.tsx       ← Main deck
    [page]/page.tsx
  slides-alt/
    layout.tsx       ← Alternate deck
    [page]/page.tsx
Each layout gets its own SlideDeck instance with different configuration.

basePath

The basePath prop tells SlideDeck which URL prefix to use for slide navigation:
app/slides-alt/layout.tsx
import { SlideDeck } from 'nextjs-slides';
import { alternateSlides } from './slides';

export default function SlidesAltLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <SlideDeck slides={alternateSlides} basePath="/slides-alt">
      {children}
    </SlideDeck>
  );
}
Now keyboard navigation goes to /slides-alt/1, /slides-alt/2, etc.
The default basePath is "/slides". Override it when your slides live at a different route.

exitUrl

Add an exit button (×) in the top-right corner that navigates to a specific URL:
<SlideDeck
  slides={slides}
  basePath="/slides-alt"
  exitUrl="/"
>
  {children}
</SlideDeck>
The exit button triggers a ViewTransition with the deck-unveil animation:
::view-transition-old(.deck-unveil) {
  animation: nxs-deck-unveil 300ms ease-out both;
}

@keyframes nxs-deck-unveil {
  to {
    opacity: 0;
    transform: scale(1.03);
  }
}
Keep SlideDeck as the direct child of the layout. Wrapping it in a <div> prevents the exit animation from working.

className for Scoped Styles

Use className to apply scoped font families and syntax themes to each deck:
app/slides-alt/layout.tsx
<SlideDeck
  slides={alternateSlides}
  basePath="/slides-alt"
  exitUrl="/"
  className="slides-alt-deck"
>
  {children}
</SlideDeck>
Then override CSS variables in your global stylesheet:
globals.css
/* Alternate deck: Playfair display font + Dracula theme */
.slides-alt-deck {
  font-family: 'Playfair Display', serif;

  /* Dracula syntax theme */
  --nxs-code-bg: #282a36;
  --nxs-code-border: #44475a;
  --nxs-code-text: #f8f8f2;
  --sh-keyword: #ff79c6;
  --sh-string: #f1fa8c;
  --sh-property: #8be9fd;
  --sh-class: #bd93f9;
  --sh-entity: #50fa7b;
  --sh-tag: #50fa7b;
  --sh-identifier: #f8f8f2;
  --sh-literal: #bd93f9;
  --sh-comment: #6272a4;
  --sh-sign: #f8f8f2;
}

Complete Example

Here’s a full setup for a second deck with Playfair + Dracula:
import { SlideDeck } from 'nextjs-slides';
import { alternateSlides } from './slides';

export default function SlidesAltLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <SlideDeck
      slides={alternateSlides}
      basePath="/slides-alt"
      exitUrl="/"
      className="slides-alt-deck"
    >
      {children}
    </SlideDeck>
  );
}

Font Integration

For custom fonts via next/font or geist:
app/layout.tsx
import { Playfair_Display } from 'next/font/google';
import { GeistSans } from 'geist/font/sans';

const playfair = Playfair_Display({ subsets: ['latin'], variable: '--font-playfair' });

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" className={`${GeistSans.variable} ${playfair.variable}`}>
      <body className={GeistSans.className}>{children}</body>
    </html>
  );
}
globals.css
.slides-alt-deck {
  font-family: var(--font-playfair), serif;
}

Props Summary

PropTypeDefaultDescription
basePathstring"/slides"URL prefix for slide routes
exitUrlstringURL for exit button (×). Shows in top-right when set.
classNamestringAdditional class for the deck container

Use Cases

Conference talks: Host multiple presentations at /talks/keynote, /talks/workshop, etc. Theme demos: Showcase different design systems or syntax themes side-by-side. Multi-language: Separate decks for different languages with different font stacks. A/B testing: Compare presentation styles with different layouts and themes.

Build docs developers (and LLMs) love