# 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

```tsx title="slides/01-intro.tsx"
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>
  );
}
```

````mdx title="slides/02-agenda.mdx"
## Today

- Author in MDX or TSX
- Theme from one place
- Present live

```ts
// fenced code is highlighted at build time, on-brand
const deck = present(slides);
```
````

Register them in order:

```tsx title="main.tsx"
import Intro from "./slides/01-intro";
import Agenda from "./slides/02-agenda.mdx";

<Present brands={["liebstoeckel"]} slides={[Intro, Agenda]} />
```
**Styling:** Use the brand's **semantic** Tailwind classes: `text-text`, `text-muted`, `text-primary`, `text-accent`, `font-heading`, `font-body`, `bg-surface`. They resolve against the active brand's tokens, so the same slide re-skins when the brand changes. See [Theming](https://docs.liebstoeckel.app/guides/theming/).

## 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.

```tsx
<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.

## 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.

```tsx
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>
);
```
**Notes are not confidential:** Speaker notes are compiled into the deck's single `.html`, which is the **same file** the audience loads in a live session. The presenter-only view is gated in the browser, not on the server, so anyone with a viewer link can recover every slide's notes from the bytes they already downloaded. Keep crib-sheet phrasing and reminders in notes — never secrets or anything you wouldn't show the audience. (`liebstoeckel build` prints a reminder when a deck contains notes.)

## 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.

```tsx
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>
```
**Magic vs. Slot: two ways to connect slides:** Both carry something across a slide change, but they're opposites:

- **`Magic`**: *different*, **stateless** elements that morph into one another. Declared inline per slide; content re-renders, so no internal state survives.
- **`Slot`** (+ the `persistent` prop): the **same** element, rendered once and projected onto each slide. State survives (an `<iframe>`, video, a live widget). See [authoring › persistent elements](https://docs.liebstoeckel.app/guides/authoring/#persistent-stateful-elements).

Rule of thumb: *morphing one thing into a different thing* → `Magic`; *the one thing keeps running* → `Slot`.
**Pair Magic with a calm transition:** A `Magic` element lives inside the slide, so a directional [slide transition](https://docs.liebstoeckel.app/guides/authoring/#slide-transitions) (`slide`/`zoom`) moves it *and* morphs it, which can look doubled. It reads cleanest with the default `fade` or with `none`. Choosing the transition for a slide that hosts a Magic move is the deck author's call.

[Animated code](https://docs.liebstoeckel.app/guides/animated-code/)
[Theming & brands](https://docs.liebstoeckel.app/guides/theming/)