Beem Slide

One page, one file

Every page of a deck is an ordinary React component on a fixed canvas.

There is no slide object in beem-slide. A page is a React component that takes no props, and a deck is an array of them. The runtime mounts one at a time onto a fixed 1920 × 1080 canvas, scales that canvas to whatever viewport it is in, and owns everything around the page — navigation, hot reload, the inspector, present mode, export.

That is the whole model. What it buys you is that a page has no ceiling: if you can express it in JSX, it is a legal page.

Where a deck lives

One directory per deck, named in kebab-case, with index.tsx as the entry:

slides/q2-launch/
├── index.tsx
└── assets/          # images, video, fonts — imported as ES modules

The directory name is the deck's id. It shows up in URLs, in the CLI's --deck filter and in the cloud, so pick something short and durable.

The contract

slides/q2-launch/index.tsx
import type { Page, SlideMeta } from '@beem-slide/core';

const fill = { width: '100%', height: '100%' } as const;

const Opening: Page = () => (
  <div
    style={{
      ...fill,
      background: '#101014',
      color: '#f4f2ee',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
    }}
  >
    <h1 style={{ fontSize: 188, letterSpacing: '-0.04em', margin: 0 }}>
      Q2, <em style={{ color: '#d56b48' }}>shipped</em>.
    </h1>
  </div>
);

const Agenda: Page = () => (
  <div style={{ ...fill, background: '#101014', color: '#f4f2ee', padding: 120 }}>
    <h2 style={{ fontSize: 84, margin: 0 }}>What we'll cover</h2>
  </div>
);

export const meta: SlideMeta = {
  title: 'Q2 launch',
  createdAt: '2026-08-20T09:00:00Z',
};

export default [Opening, Agenda] satisfies Page[];

Two hard requirements, and that is genuinely all of them:

  1. export default is a non-empty array of zero-prop components, in the order they should be presented.
  2. Each component fills its container. Set width: '100%' and height: '100%' on the root element and lay out however you like inside.

The optional exports

Everything else on the module is opt-in.

meta labels the deck. title is what the home screen and the header show — without it you get the directory name. createdAt is an ISO 8601 string literal used to sort the deck list newest-first. theme is the id of a file under themes/, and setting it back-links the deck to that theme in the themes gallery.

design declares typed design tokens — palette, fonts, type scale, corner radius — which the framework turns into CSS variables at the canvas root and the Design panel edits live. See Themes.

notes is an array of speaker notes, index-aligned with the page array, read by the presenter console.

transition sets one house animation for the whole deck; an individual page can override it by assigning transition to the component itself.

Nothing in between

No DSL, no frontmatter pipeline, no template language, no component library you have to lay out inside of. The page is the file, the file is React, and the diff you review is the change you shipped.

On this page