OpenPress

Slides

Create Slides

Create a portable OpenPress slide workspace with Press markers, a template registry, slide source files, theme CSS, and the core Object API.

An OpenPress slide workspace is not built from large layout wrappers. The current direction is: define reusable templates first, then let the CLI or Workbench copy a template into a new slide source folder.

Templates should compose Slide, Frame, Text, Line, MediaObject, and other core objects directly. Put visual styling in theme CSS, editable text in Text children, fixed placement in box, and flow constraints in Frame layout.

Step 1: Initialize the workspace

npm create @open-press@latest <project-name> -- --type slides

This creates a slide Press with a 16:9 page geometry. OpenPress slide coordinates use a 1920 x 1080 base canvas.

Step 2: Keep press.tsx as slide registration

press/<slug>/press.tsx should stay simple. It describes deck order; each slide’s actual layout lives in its slide source file.

import { Press, Slide } from "@open-press/core";

export default function SlidePress() {
  return (
    <Press slug="slide" title="Deck Title" type="slides" page="slide-16-9">
      <Slide id="cover" />
      <Slide id="agenda" />
      <Slide id="statement" />
    </Press>
  );
}

Step 3: Create slides from templates

Templates are registered in press/<slug>/slide-style/manifest.json. When you add a slide, the CLI copies the selected template from slide-style/templates/<template>/ into slides/<id>/.

node packages/core/engine/cli.mjs slide . add intro --press slide --template cover

Common structure:

press/slide/
  press.tsx
  theme/default.css
  slide-style/
    manifest.json
    theme/default.css
    templates/
      cover/slide.tsx
      agenda/slide.tsx
  slides/
    intro/slide.tsx

slide-style/theme/default.css is the source style for the template package. After it is copied or synced into the workspace, the actual deck uses press/<slug>/theme/default.css.

Step 4: Write slide source with core objects

Slide source should use core objects directly instead of hiding editable content inside abstract wrapper props.

import { Frame, Line, Slide, Text } from "@open-press/core";

export default function CoverSlide() {
  return (
    <Slide id="cover" className="op-source-deck-slide">
      <Frame frameKey="canvas" chrome={false} className="op-source-deck-canvas">
        <Text as="p" label="date" box={{ x: 100, y: 80 }} className="op-source-deck-date">
          26 JUNE 2024
        </Text>
        <Text as="h1" label="title" box={{ x: 100, y: 360, w: 1155 }} className="op-source-deck-title">
          A line is length without breadth.
        </Text>
        <Line label="red-rule" box={{ x: 100, y: 774, w: 270, h: 4 }} className="op-source-deck-red-rule" />
      </Frame>
    </Slide>
  );
}

Step 5: Verify

npm run build

For local preview, run:

npm run dev:workspace

See Core Object API for object identity, label, box, and Frame layout rules.