Your first deck
A deck is an ordered list of slide modules handed to <Present>. Each module’s default export is the slide; an optional notes export shows in the presenter view.
A slide is a module
Section titled “A slide is a module”import { Step } from "@liebstoeckel/engine";
export const notes = ( <div> <p>Open strong. Reveal each point with <kbd>→</kbd>.</p> </div>);
export default function Intro() { return ( <div className="w-full"> <h1 className="font-heading text-7xl font-semibold text-text"> Decks that <span className="italic text-primary">talk back</span>. </h1> <div className="mt-8 space-y-3 font-body text-2xl text-muted"> <Step>Plugins are real Bun packages.</Step> <Step>State is shared live over a CRDT.</Step> </div> </div> );}## Today
- Author in MDX or TSX- Theme from one place- Present live
```ts// fenced code is highlighted at build time, on-brandconst deck = present(slides);```Register them in order:
import Intro from "./slides/01-intro";import Agenda from "./slides/02-agenda.mdx";
<Present brands={["liebstoeckel"]} slides={[Intro, Agenda]} />Progressive reveals with <Step>
Section titled “Progressive reveals with <Step>”Wrap anything in <Step> to reveal it on the next press. Steps reveal in document order; once the last step is shown, the next press advances the slide.
<Step>First this…</Step><Step>…then this.</Step>The presenter view shows a prominent step counter so you always know whether a press will reveal or advance.
How reveals behave when you change slides
Section titled “How reveals behave when you change slides”Reveals replay in reverse when you go backwards. Pressing ← hides the last
revealed step, and once a slide is fully hidden the press before that takes you
to the previous slide with all of its reveals already shown — the state your
audience last saw it in, the same way PowerPoint and Keynote behave. Going
forwards is the mirror image: you enter each slide unrevealed and build it up.
Jumping is different from stepping, and deliberately so. Picking a slide in the
overview (o) or typing its number lands on that slide unrevealed, whichever
slide you came from and however far into it you were.
On the last slide, once everything is revealed, the next press ends the deck
rather than advancing. The deck shows a deliberate end card — ← or Esc goes
back into the deck, o opens the overview, r restarts.
Ending is a property of the deck, not of one window, so you can do it from the
presenter view and the audience screen follows. The presenter’s forward button
reads End → for that last press and then Ended, and Back takes both windows
out of the end card and returns you to the final slide with its reveals intact.
Speaker notes
Section titled “Speaker notes”Export notes (plain JSX) from a slide module. The presenter window renders it in a styled panel alongside the current/next slide previews and a timer.
export const notes = ( <div> <p>Key point. Then mention the <strong>demo</strong>.</p> <ul><li>Press <kbd>Q</kbd> to show the QR.</li></ul> </div>);Magic Move
Section titled “Magic Move”<Magic> morphs one slide’s element into the next slide’s element with the same id. Motion FLIP-animates position and size and crossfades the content. Declare each one inline on its slide; the two can differ (text → text, small → large), so it’s true Keynote-style Magic Move.
import { Magic } from "@liebstoeckel/engine";
// On slide 1:<Magic id="logo" className="text-4xl">●</Magic>// On slide 2, same id, new place/size (and even new content) → it morphs there:<Magic id="logo" className="text-8xl absolute top-10 right-10">◆</Magic>Code-first presentations your agent can author. One file out, no server.
Comments