LogotypeSlidebook

Slidebook

Slidebook is a flexible ecosystem for building AI-assisted presentations with code.

OverviewΒ 

Slidebook is a developer-friendly tool for creating and running slideshows using JSX, Tailwind, and motion β€” with built-in live preview, collaboration, theming, and more.

It consists of four packages:

PackageDescription
@slidebook/cliCLI tool to develop, build, run, or eject a Slidebook project.
@slidebook/coreInternal logic and components β€” embed slides, manage layout, sync state.
@slidebook/imageA ready-to-use version of Slidebook without custom coding.
@slidebook/serverReal-time collaboration server β€” slide syncing, remote control, etc.

Modes of OperationΒ 

🟒 Simplified Mode 

Zero configuration needed. Just create a slides/ folder and drop in your slides:

slides/
1.tsx
2.tsx
slide-3.tsx

πŸ”§ Professional ModeΒ 

Offers full control over structure and rendering.

Run:

slidebook eject

This will scaffold a full Next.js app using @slidebook/core.

How to UseΒ 

CommandsΒ 

slidebook dev       # Start local server with hot reload
slidebook build # Build the app
slidebook start # Run production build
slidebook eject # Switch to full custom project mode

Note

All slides are React Server Components by default, so you can fetch data directly inside a slide:

const data = await db.query("SELECT * FROM ...");

FeaturesΒ 

ConfigurationΒ 

Settings can be passed via:

Priority: arg > env > config > default

Example slidebook.config.jsΒ 

// @ts-check

/**
* @type {import('@slidebook/cli/lib/config').Config}
*/
export default {
slide: {
width: 1200,
height: 600,
},
app: {
serverUrl: "http://localhost:3000",
qrUrl: "https://slidebook.dev",
port: 3000,
},
auth: {
password: "qwerty",
},
};

Full OptionsΒ 

Keyconfig pathargenv varDefault
serverUrlapp.serverUrl--serverUrlSERVER_URLβ€”
qrUrlapp.qrUrl--qrUrlQR_URLβ€”
portapp.port--portPORT3000
passwordauth.password--passwordPASSWORDqwerty
widthslide.width--slideWidthSLIDE_WIDTH1200
heightslide.height--slideHeightSLIDE_HEIGHT600
cookiesFlagscookies.flags--cookiesFlagsCOOKIES_FLAGSSameSite=Strict;
authenticateauth.authenticateβ€”β€”β€”
validateauth.validateβ€”β€”β€”

Real-Time SyncΒ 

When the host changes a slide, theme, or QR code:

Host ViewΒ 

Shows:

Requires host password to access. Set via config, CLI, or env (read more).

ThemesΒ 

Add a theme by importing it into layout.tsx (pro mode) or layer.tsx (simplified mode):

import "@slidebook/core/lib/assets/themes/pink-neutral.css";

Available themes:

Project Structure (Pro Mode)Β 

.
β”œβ”€β”€ src/
β”‚ β”œβ”€β”€ app/ # Next.js app directory
β”‚ β”‚ β”œβ”€β”€ [[...pathname]]/ # Slide route segment
β”‚ β”‚ β”‚ └── page.tsx # Renders current slide
β”‚ β”‚ β”œβ”€β”€ layout.tsx # App layout with theme and wrapper
β”‚ β”‚ └── globals.css # Global styles
β”‚ └───slides/ # Your slides, one file per slide
β”‚ β”œβ”€β”€ 0.tsx # First slide
β”‚ β”œβ”€β”€ 1.tsx # Second slide
β”‚ └── index.tsx # Optional wrapper for all slides
β”œβ”€β”€ public/ # Static assets
β”œβ”€β”€ slidebook.config.js # Config file
└── package.json

Slides segmentΒ 

import { RootPage } from "@slidebook/core/lib/components/root-page";
import { generateStaticParamsFactory } from "@slidebook/core/lib/lib/generate-static-params";
import { slides } from "../slides";

export const generateStaticParams = generateStaticParamsFactory(slides.length);

export default async function SlidePage({ params }: { params: Promise<{ pathname: string[] }> }) {
const { pathname } = await params;
return <RootPage segments={pathname} slides={slides} />;
}

Slides definitionΒ 

export const slides = [
{ component: Slide1, notes: Notes1 },
{ component: Slide2 },
];

LayoutΒ 

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { SlideLayer } from "@slidebook/core/lib/components/slide-layer";
import { Layer } from "./slides/layer";

import "./globals.css";
import "@slidebook/core/lib/styles.css";

export const metadata: Metadata = {
title: "Slidebook",
description: "Advanced presentation tool",
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body className={Inter({ subsets: ["latin"] }).className}>
<Layer>
<SlideLayer>{children}</SlideLayer>
</Layer>
</body>
</html>
);
}

export const dynamic = "error";

Project structure (Simplified Mode)Β 

.
β”œβ”€β”€ slides/ # Your slides, one file per slide
β”‚ β”œβ”€β”€ 0.tsx # First slide
β”‚ β”œβ”€β”€ 1.tsx # Second slide
β”‚ └── layer.tsx # Optional wrapper for all slides
β”œβ”€β”€ public/ # Static assets
β”œβ”€β”€ slidebook.config.js # Config file
└── package.json

SlideΒ 

export const Slide = () => (
<h1 className="text-4xl font-bold text-center text-white">Hello World</h1>
);

export const Notes = () => (
<p>Welcome notes for host view</p>
)

LayerΒ 

export const Layer = ({ children }) => (
<div className="p-12">{children}</div>
);

βš™οΈ Running the AppΒ 

You can start the presentation app and server together or separately.

slidebook start

Runs both server and editor in one command β€” enabling:

Tip

Recommended for local use and self-hosting

🧩 Alternative: Separate processes 

slidebook start server
slidebook start app

Useful if you're deploying to environments like Vercel, which do not support WebSocket or real-time infrastructure.

Important

When running separately, pass the server URL to the app

// slidebook.config.js
export default {
app: {
serverUrl: "https://your-slidebook-server.example.com",
},
};

πŸ“¦ DeploymentΒ 

To static hosts (Vercel, Netlify)Β 

Only the app can be deployed. Real-time features will be unavailable unless the server is deployed separately.

To self-hosted server (Docker, Fly.io)Β 

Run slidebook start or split as needed. Pass serverUrl when decoupling.

AdditionalΒ 

Please consider giving a star if you like it, this motivates the author to continue working on this and other solutions ❀️

Create issues with wishes, ideas, difficulties, etc. All of them will definitely be considered and thought over.

LicenseΒ 

MITΒ 

Last modified on