open-slide Documentation

A slide framework built for agents.

5,662 stars TypeScript TypeScript 1 file Β· ~3,897 tokens #agent#react#slides
RAW Doc

File: README.md

open-slide



The slide framework built for agents. Describe your deck in natural language β€” your coding agent writes the React. open-slide handles the canvas, scaling, navigation, hot reload, and present mode so the agent can focus on content.

Every slide renders into a fixed 1920 Γ— 1080 canvas. Pages are arbitrary React components, not a constrained DSL.

bash
npx @open-slide/cli init my-slide

Why open-slide

Slides are visual code. Agents are great at writing code. open-slide is the missing runtime that turns "make slides about X" into a polished, presentable deck β€” without you ever leaving the chat.

Highlights

πŸ€– Agent-native authoring

Works with any coding agent (Claude Code, Codex, Cursor, …). The scaffolder ships with built-in skills:

  • /create-slide β€” drafts a deck end-to-end. Asks four scoping questions (topic & aesthetic, page count, text density, motion vs. static), picks an id, plans the structure, and writes the pages.
  • /slide-authoring β€” the technical reference for the 1920 Γ— 1080 canvas, type scale, palette, and layout rules. The agent reads this before writing.

From a one-line prompt to a polished deck, no boilerplate.

🎯 In-browser inspector

Click any element in the dev server and attach a comment β€” "make this red", "change to 'Open Slide Rocks'", "shrink the headline". Comments are persisted as @slide-comment markers in source. Run /apply-comments and the agent applies every pending edit, then clears the markers.

The loop: present β†’ click to comment β†’ /apply-comments β†’ repeat.

Manage images, videos, and fonts per deck through a built-in assets panel. Search and drop in any brand logo via the integrated svgl catalogue β€” no more hunting for SVGs.

🎬 Professional present mode

Fullscreen playback with keyboard navigation, plus a presenter mode with current/next slide preview, speaker notes, and a timer. Built for the stage, not just the browser tab.

πŸ“¦ Export to static HTML & PDF

One command exports your deck as a self-contained static HTML site or a print-ready PDF. Share without a server.

πŸ“ Slide manager

Organise decks into folders with custom emoji and drag-and-drop to reorder. Useful once you've built more than three decks and need to find anything.

πŸš€ Deploy-friendly

Outputs a plain static build β€” one-click deploy to Vercel, Cloudflare Pages, Zeabur, Netlify, or any static host. No server, no runtime, no lock-in.

Get started

bash
npx @open-slide/cli init my-slide
cd my-slide
pnpm dev

The scaffolded workspace ships with agent skills preconfigured for Claude Code. From there you drive the deck through your agent β€” or edit slides//index.tsx directly. See CLAUDE.md for the hard rules.

Repo layout

This repo is a pnpm + Turbo monorepo.

Path Description
packages/core @open-slide/core β€” runtime (home page, slide viewer, present mode, inspector), Vite plugin, and the open-slide dev/build/preview CLI.
packages/cli @open-slide/cli β€” npx @open-slide/cli init scaffolder. Generates a minimal workspace where Vite/React/tsconfig stay hidden inside core.
apps/demo Example workspace that consumes @open-slide/core via workspace:*. Used for local development of the framework.

Development

bash
pnpm install
pnpm dev      # runs the demo against the local @open-slide/core
pnpm build    # builds all packages
pnpm check    # type-checks all packages
pnpm lint     # lints via biome

Support

If open-slide has been useful to you, consider supporting development:

License

MIT Β© Yiwei Ho


File: apps/web/content/docs/core-feature/assets-manager.mdx


title: Assets manager

Assets come in two scopes:

  • Slide-local β€” one-off files only used by a single deck. They live next to
    the deck that uses them and are imported with a relative path.
  • Global β€” files reused across decks or themes (company logos, presenter
    avatars, recurring icons). They live in a top-level assets/ folder and are
    imported through the @assets/* Vite alias.
text
project-root/
β”œβ”€β”€ assets/                  # global β€” shared across decks
β”‚   β”œβ”€β”€ acme.svg
β”‚   └── avatar.png
└── slides/
    └── q2-launch/
        β”œβ”€β”€ index.tsx
        └── assets/          # slide-local β€” only this deck
            β”œβ”€β”€ cover.png
            β”œβ”€β”€ chart.svg
            └── intro.mp4
tsx
import cover from './assets/cover.png';      // slide-local
import chart from './assets/chart.svg';      // slide-local
import logo from '@assets/acme.svg';         // global

const Cover = () => (
  <>
    
    
  </>
);

Both paths run through Vite's normal asset pipeline β€” files get hashed and
emitted on build like any other import.

In-browser asset manager

The dev server has an Assets panel with a Slide / Global scope toggle
at the top:

  • Slide scope reads and writes slides//assets/.
  • Global scope reads and writes the project root assets/ folder.

Drag files in to upload them. Rename and replace from the same pane the
inspector uses to swap an element's src β€” the Replace picker carries the
same scope toggle, and the rewritten import uses ./assets/... or
@assets/... to match the source.

The home sidebar also exposes the global manager directly: click Assets
under Themes to open the locked-global view at /assets.

Need a brand logo? The Assets panel has an svgl search powered by
svgl.app. Search, pick, drop β€” the SVG lands in whichever
scope is active (slide-local or global) and you can import it immediately.


File: apps/web/content/docs/core-feature/export.mdx


title: Export

open-slide build produces a plain static site under dist/ β€” everything
renders on the client, so no server is needed.

Static HTML

npm
npm run build
npm run preview     # serves dist/ for sanity-checking

dist/ is portable. Drop it on Vercel, Cloudflare Pages, Netlify, Zeabur,
GitHub Pages β€” anything that hosts files.

From the toolbar

The Export menu in the slide toolbar exports the active deck directly:

  • HTML β€” a static HTML snapshot of the deck. Decks that reference
    assets download as a zip (HTML file + assets folder).
  • PDF β€” one 1920 Γ— 1080 landscape PDF page per deck page. Not supported
    in Safari.
  • PPTX (images) β€” each page rendered as an image on a PowerPoint slide.
    Native editable PPTX export is not available yet.

What gets shipped

The build pipeline only includes:

  • The decks under slides/.
  • The assets each deck imports.
  • The runtime β€” viewer, scaler, present mode (configurable; see below).

You can trim the surface area for a public share by toggling fields in
open-slide.config.ts:

ts
import type { OpenSlideConfig } from '@open-slide/core';

const config: OpenSlideConfig = {
  build: {
    showSlideBrowser: false,    // hide the deck index
    showSlideUi: false,         // hide on-canvas UI (toolbar etc.)
    allowHtmlDownload: false,   // hide the export menu (HTML / PDF / PPTX)
  },
};

export default config;

File: apps/web/content/docs/core-feature/inspector.mdx


title: Inspector

The inspector is a dev-only overlay built into the open-slide runtime. Toggle
it from the toolbar (or press i), then click any element on the slide.

Two surfaces

The inspector exposes two ways to edit a slide:

Visual editor

Click an element. A property panel opens with editable inputs:

  • Text β€” replace inline.
  • Typography β€” font family, weight, size, letter-spacing.
  • Colour β€” text colour, background colour.
  • Image src β€” swap to any file in the deck's or the global assets
    folder; see the assets manager for
    how the two scopes work.

All edits buffer in memory until you press Save in the SaveBar. One save
lands as a single HMR write to disk.

Comments

Sometimes the change is easier to describe than to perform. Click an element,
pick Comment, type a note:

use the accent colour on this title

The inspector pins the note as an @slide-comment marker in the source. The
marker travels with the element and is invisible at runtime. Run
/apply-comments in your agent to turn the notes into edits β€” see
/apply-comments.

Selection is visible to your agent

Whenever you click, the inspector publishes the picked element to a file
your agent reads via /current-slide β€” so
"make this bigger" resolves to the exact JSX node with no "which one?"
round-trip.


File: apps/web/content/docs/core-feature/present-mode.mdx


title: Present mode

Fullscreen playback

From the dev server, hit Present (or press f). The current deck goes
fullscreen, scaled uniformly to fit the screen:

  • Arrow / space / PgDn to advance.
  • ← / ↑ / PgUp to go back.
  • Home / End to jump to first / last.
  • Esc to exit.

Presenter view

Press p (or the presenter button in the present control bar) to open the
presenter view in a second window:

  • Current slide at the size you'll show it.
  • Next slide preview.
  • Speaker notes for the current page.
  • Timer β€” elapsed time since you entered present mode.

Keep it on the laptop screen while the deck mirrors to the projector.

Speaker notes

Add notes alongside the page array β€” an array of strings, index-aligned with
the pages (use undefined to skip a page):

tsx
export const notes = [
  'Open with a smile. Mention the analyst quote from yesterday.',
  undefined,
  'Pause here for questions. The chart is a hand-off.',
];

File: apps/web/content/docs/core-feature/themes.mdx


title: Themes

A theme is a bundle of two paired files under themes/:

  • themes/.md β€” agent-facing recipe: palette, typography, layout,
    fixed components, motion. create-slide reads this before authoring.
  • themes/.demo.tsx β€” a runnable mini-slide that demonstrates the
    theme. The dev UI's Themes panel imports it and renders it as the
    theme's live preview card.

Both files share the same stem so the runtime can pair them automatically.
If you author more than two decks you'll want them to look related β€” a theme
captures the recipe in one place any deck can reference, and the demo makes
it browsable in the dev UI before you pick one.

File layout

text
themes/
β”œβ”€β”€ corporate.md
β”œβ”€β”€ corporate.demo.tsx
β”œβ”€β”€ editorial.md
β”œβ”€β”€ editorial.demo.tsx
β”œβ”€β”€ retro-print.md
└── retro-print.demo.tsx

The markdown is free-form. A useful template:

md title="themes/corporate.md"
---
name: Corporate
mode: dark
---

# Corporate

## Palette
- ink: #0a0a0c
- accent: #4a52b5
- mint: #1f8458

## Typography
- display: 'SΓΆhne', system-ui
- mono: 'JetBrains Mono'

## Voice
- Tight, declarative, never coy.
- One concept per slide.

The demo is a normal slide module β€” same shape as slides//index.tsx,
just placed under themes/ so the runtime treats it as preview-only (it
does not appear in the slides list):

tsx title="themes/corporate.demo.tsx"
import type { Page } from '@open-slide/core';

const Cover: Page = () => (/* …inline Title / Footer using theme tokens… */);
const Content: Page = () => (/* … */);

export default [Cover, Content];

Keep the demo's inline Title/Footer/Eyebrow components verbatim in sync
with the snippets in the markdown β€” what authors see in the Themes panel
should match what create-slide will paste into a real slide.

Using a theme

When you call /create-slide, mention the theme by name:

text
/create-slide for "Q3 board update β€” use the corporate theme"

The agent loads themes/corporate.md, applies the palette and type stack,
and writes pages that match.

Extracting a theme

Already have a deck whose look you like? Use
/create-theme to extract its design tokens
into a reusable theme file.


File: apps/web/content/docs/cli/build.mdx


title: open-slide build

npm
open-slide build
# or
npm run build

Builds every deck under slides/ into a self-contained static site at
dist/. The output has no server requirement β€” drop it on any static host.

Flags

Flag Default Description
--out-dir <dir> dist Write the static build to a custom folder.

Output

text
dist/
β”œβ”€β”€ index.html
β”œβ”€β”€ assets/
β”‚   └── ...hashed files...
└── ...

Configuration

Two open-slide.config.ts fields matter at build time:

  • For a public share, hide the slide browser and on-canvas UI with the
    build toggles β€” see Export.
  • If the build won't sit at the domain root (GitHub Pages project sites, a
    reverse-proxy folder), set base so asset URLs and navigation resolve
    against the deployed path β€” see Config.

File: apps/web/content/docs/cli/dev.mdx


title: open-slide dev

npm
open-slide dev
# or, via the generated script
npm run dev

Boots a Vite-powered dev server on http://localhost:5173 (or the next free
port). Hot module reload is wired up for both the runtime and your slide
files β€” saving an index.tsx updates the canvas without losing slide state.

What you get

  • Slide browser β€” list of every deck under slides/.
  • Canvas β€” the active page, scaled to fit the viewport.
  • Inspector β€” click any element to edit it visually, drop a
    @slide-comment, or both.
  • Assets panel β€” drag, rename, replace, plus svgl logo search.
  • Present mode β€” fullscreen playback with presenter view.

Flags

Flag Default Description
-p, --port from config Override the listening port.
--host [host] localhost only Expose the dev server on the network. Optional host pin.
--open off Open the browser on start.
--no-skills-check off Skip the built-in skills drift check.

The skills check also obeys the OPEN_SLIDE_SKIP_SKILLS_CHECK=1
environment variable β€” useful in CI or container builds where stdin
isn't a TTY.

Configuration

Override the port (and a few other knobs) in open-slide.config.ts:

ts title="open-slide.config.ts"
import type { OpenSlideConfig } from '@open-slide/core';

const config: OpenSlideConfig = {
  port: 5174,
  slidesDir: 'slides',
};

export default config;

Accessing the dev server through a proxied domain (Coder, Codespaces, a
reverse proxy) and hitting Blocked request. This host is not allowed.?
Set allowedHosts
in the config.