@open-carousel/core
v1.13.2
Published
Runtime and CLI for open-carousel — write slides in slides/, we handle the rest.
Maintainers
Readme
@open-carousel/core
Runtime and CLI for open-carousel — a React-based slide framework where you write slides and the framework handles the Vite/React stack, layout, navigation, hot reload, and fullscreen play mode.
Install
pnpm add @open-carousel/coreMost users get this installed automatically by running npx @open-carousel/cli init. Use this package directly only if you're wiring up an existing workspace by hand.
What's inside
- Runtime — home page, slide viewer, thumbnail rail, keyboard navigation, and fullscreen presenter mode. Every slide renders into a fixed-size canvas (default 1920×1080, configurable per deck via
meta.format); the framework scales it. - Vite plugin — discovers
slides/<id>/index.{tsx,jsx,ts,js}, exposes them via virtual modules, and reloads when slides are added or removed. - CLI —
open-carousel dev | build | previewso workspaces never need to touch Vite, React, or tsconfig directly.
CLI
Once installed, the open-carousel bin is available in the workspace:
| Command | Description |
| --- | --- |
| open-carousel dev | Start the dev server. Flags: -p, --port <port>, --host [host], --open. |
| open-carousel build | Build a static site. Flags: --out-dir <dir> (defaults to dist). |
| open-carousel preview | Preview the production build. Flags: -p, --port <port>, --host [host], --open. |
Config
Create open-carousel.config.ts in the workspace root (all fields optional):
import type { OpenCarouselConfig } from '@open-carousel/core';
const openCarouselConfig: OpenCarouselConfig = {
slidesDir: 'slides',
port: 5173,
};
export default openCarouselConfig;Hosting under a subpath
Set base to deploy the built site under a sub-directory (intranet folders, GitHub Pages project sites, reverse proxies). Use a leading and trailing slash:
const openCarouselConfig: OpenCarouselConfig = {
base: '/my-slides/',
};The value is passed straight to Vite's base and to React Router's basename, so client-side navigation matches the deployed path.
Authoring slides
Slides live under slides/<kebab-case-id>/index.tsx and default-export an array of Page components:
import type { Page } from '@open-carousel/core';
const Cover: Page = () => (
<div className="flex h-full w-full items-center justify-center">
<h1 className="text-[120px] font-bold">Hello, open-carousel</h1>
</div>
);
const pages: Page[] = [Cover];
export default pages;
export const meta = { title: 'Hello' };Canvas format
Each deck declares its canvas via meta.format — a preset id or explicit pixel dimensions. Omitting it keeps the classic 1920×1080 landscape canvas.
| Preset | Dimensions | Aspect | Typical use |
| --- | --- | --- | --- |
| landscape (default) | 1920×1080 | 16:9 | Talks, classic decks |
| portrait | 1080×1350 | 4:5 | Instagram / LinkedIn feed carousels |
| square | 1080×1080 | 1:1 | Universal feed |
| story | 1080×1920 | 9:16 | Stories, Reels, TikTok |
export const meta = { title: 'My carousel', format: 'portrait' };
// or custom dimensions:
export const meta = { title: 'Banner', format: { width: 1200, height: 628 } };The viewer, thumbnails, present mode, and every export (PDF, static HTML, PPTX) follow the declared format.
Exports
import {
CANVAS_WIDTH, // 1920 (landscape default)
CANVAS_HEIGHT, // 1080 (landscape default)
CANVAS_FORMATS, // preset id → { width, height }
resolveCanvasSize, // CanvasFormat → { width, height }
slideCanvasSize, // SlideModule → { width, height }
type CanvasFormat,
type CanvasFormatId,
type CanvasSize,
unstable_SharedElement, // match or fade objects across pages for shared element transitions
type Page,
type SlideMeta,
type SlideModule,
type SlideTransition,
type OpenCarouselConfig,
} from '@open-carousel/core';The Vite plugin is exposed under a subpath for advanced setups:
import { createViteConfig } from '@open-carousel/core/vite';License
MIT
