# Building & deploying

## One self-contained file

A deck builds to a single self-contained file with JS and CSS inlined and assets base64'd. There's nothing else to host. The file is named after the deck folder, so `my-talk/` builds to `dist/my-talk.html`.

```bash
liebstoeckel build my-talk        # → my-talk/dist/my-talk.html
```

The scaffolded `build.ts` does the same thing, so `bun run build` inside the deck works too:

```ts title="build.ts"
import { buildDeck } from "@liebstoeckel/thumbnails/build";

// builds the single file, then embeds slide thumbnails (skips gracefully
// if no Chromium / when LIEBSTOECKEL_NO_THUMBS=1)
await buildDeck({ entry: "./index.html", outdir: "./dist" });
```

## What ends up in the file

- A **generator stamp** in the head (an HTML comment plus a `<meta name="generator">`) recording the engine and CLI versions that built it, so you can tell what produced a file. See the [file format reference](https://docs.liebstoeckel.app/reference/file-format/#generator-header).
- Your bundled, minified JS (engine + slides + plugins' client code).
- The compiled CSS (Tailwind + brand variables + code/atmosphere styles).
- Pre-tokenized highlighted code (no Shiki at runtime).
- The **plugin manifest**: a JSON `<script>` listing the deck's plugins, with any server bundles base64-encoded (decoded + run only by a live server, never in the browser).
- **Slide thumbnails**: a manifest of WebP data-URIs for the overview grid (see below).
- **Third-party license notices**: an inert `<script>` listing the licenses of everything
  bundled into the file (the libraries, the fonts, and the MPL-2.0 engine). Minification
  strips license comments, so the build puts the required attribution back. It's computed
  from what *this* build bundled, so it stays correct when you swap a font or add a library.
  Inspect or CI-gate it with [`liebstoeckel licenses`](https://docs.liebstoeckel.app/reference/cli/#licenses).

## Deploying

Because it's one static file, deploy anywhere:

- Open `dist/<deck-slug>.html` directly (file URL); it just works offline.
- Drop it on any static host (S3, GitHub Pages, Netlify, a plain web server).
- Email it / put it in a shared drive.

To present it **live** to a room or the internet, you don't deploy the file. You run [`liebstoeckel live`](https://docs.liebstoeckel.app/guides/live/) (optionally [via a relay](https://docs.liebstoeckel.app/guides/relay/)).

## Opting out of thumbnails

Thumbnails need a headless Chromium (see [Chromium setup](https://docs.liebstoeckel.app/guides/chromium/) for how to provide one). The build **skips them gracefully** (with a note, never failing) when none is available or when you set:

```bash
LIEBSTOECKEL_NO_THUMBS=1 liebstoeckel build my-talk
```

[Thumbnails](https://docs.liebstoeckel.app/guides/thumbnails/)
[Chromium setup](https://docs.liebstoeckel.app/guides/chromium/)