Presentations written as HTML, made for AI agents to edit.

One file per slide, a theme in CSS, and Reveal.js to present it. When the talk is over, send the whole deck as one HTML file.

pnpm dlx byeslide init my-deck
Open the example decks
Inks

Byeslide

Open source under the MIT license. Published on npm.

One slide, three plates

A print shop makes a page from separate plates, one per ink. Byeslide keeps a slide's content, theme and runtime apart the same way, so each change lands in one file.

  1. Content

    content/01-title.md holds the words and speaker notes. slides/01-title.html puts them on the slide.

  2. Theme

    Inks, fonts and sizes are CSS custom properties in theme.css. Layout classes live in styles.css.

  3. Runtime

    Reveal.js presents the deck: transitions, fragments, the speaker view and the print view.

  4. Build

    byeslide build prints the three in register, as dist/index.html.

An agent edits one small file

A .pptx stores every position as a number. A Byeslide slide stores its words and structure, and the look comes from shared CSS. An agent changes a slide without doing layout arithmetic.

  1. Write the words

    Each slide has a Markdown file in content/ with its words and speaker notes. It says nothing about the look, so anyone on the team can edit it.

    content/04-folder.md# A deck is a folder you can read
    
    Seven entries, one job each.
    
    - `theme.css`, **Design tokens**:
      fonts, inks and sizes.
    - `slides/`, **One file per slide**:
      file names set the order.
    
    ## Speaker notes
    
    Walk the folder one entry per click.
  2. Ask an agent to update the slide

    The agent reads the content file and the closest pattern, then edits one slide file. Skills in .codex/skills/ tell it where to look.

    slides/04-folder.html<section class="slide">
      <h2 class="heading">A deck is a folder
        you can read</h2>
      <ul class="tree">
        <li class="fragment">theme.css</li>
        <li class="fragment">slides/</li>
      </ul>
      <aside class="notes">Walk the
        folder one entry per click.</aside>
    </section>
  3. Check before you present

    byeslide check opens every slide in Chromium and reports text that does not fit, with the file it came from.

    $ byeslide check
    Overflow detected:
    - slides/09-check.html (#9) axis=y
      offenders: p
    
    $ byeslide check
    No overflow detected across 14 slides.

Present it, print it, or send it as one file

The starter deck: 59 files in dist/, one 3.6 MB file after byeslide bundle.

Three starter decks

byeslide init asks which deck to start from. Each one has its own look, patterns and content, and each slide shows a technique you can copy. Open a slide to see it live.

Start a deck

You get the starter deck. Replace it one slide at a time, or ask an agent to.

Needs Node.js 22 or later and pnpm. Run pnpm install:browsers once before pnpm check or pnpm pdf.

pnpm dlx byeslide init my-deck
cd my-deck
pnpm install
pnpm preview

Deck structure

A deck is a normal folder. You edit the source files. The build writes the presentation to dist/.

my-deck/
  deck.config.js    title, size, plugins
  theme.css         design tokens
  styles.css        layout classes
  content/          words and notes, one Markdown file per slide
  patterns/         example slides to copy
  slides/           one HTML file per slide
  assets/           fonts, images, video, scripts
  dist/             build output

File names set the slide order: slides/01-title.html comes before slides/02-agenda.html. Never edit dist/ by hand. The next build replaces it.

Starter templates

byeslide init asks which starter deck to begin from. Use the arrow keys or a number, then Enter. To choose without the question, pass --template:

pnpm dlx byeslide init my-deck --template lesson
tour (default)
Presents Byeslide itself. Each slide shows one technique: 3D, charts, fragments, video.
report
A board-style quarterly review for a made-up company: executive summary, exhibits, risks and decisions.
lesson
A science lesson for ages 10 to 12, "Why does the Moon have phases?", with a live model, predictions and an exit ticket.

Each template has its own theme, patterns and content files. The agent skills are the same in all of them. When init runs without a terminal, for example from an agent or a script, it does not ask: it uses tour and says so. byeslide templates lists the templates.

Content files

content/NN-name.md holds the words, data and speaker notes for slides/NN-name.html. People who do not write HTML edit these files, then ask an agent to update the slides.

# Pilot plan

Two teams start in March. We decide in May whether to widen the pilot.

## Speaker notes

Pause here for questions.

A content file describes what the audience sees and hears, not how it looks. The look comes from theme.css, styles.css and the slide file.

Writing slides

  1. Write or update the slide's words in content/NN-name.md.
  2. Pick the closest file in patterns/.
  3. Copy it to slides/NN-name.html and replace the content.
  4. Run pnpm build, then pnpm check.

A slide file is an HTML fragment or a single <section>. The build wraps fragments in a Reveal <section>. Full HTML documents also work: the build uses their <body>.

Put speaker notes in <aside class="notes"> inside the slide. Use Reveal features as usual: class="fragment", data-auto-animate, data-background-color, and the rest.

Scripts in slides

A slide can load a library and run its own setup code. The build moves slide scripts after Reveal starts. It keeps every inline script, and it loads a shared external script only once.

<canvas data-chart></canvas>
<script src="./assets/vendor/chart.umd.js"></script>
<script>
  const slide = Byeslide.slideForScript(document.currentScript);
  new Chart(slide.querySelector("[data-chart]"), config);
</script>

In an inline module script, use Byeslide.slideForScript(import.meta) or import.meta.byeslideSlide. Add data-byeslide-repeat to an external script that must run once for each slide that includes it. Keep libraries in assets/vendor/ so the deck works offline.

deck.config.js

OptionDefaultUse
title, description"Untitled Byeslide Deck", ""Page title and meta description. bundle and pdf name their files after the title.
width, height1920, 1080The fixed logical slide size. check measures against it.
theme, styles"theme.css", "styles.css"CSS files for the deck. Each can be a list.
plugins["notes", "highlight", "search", "zoom"]Reveal plugins. markdown and math also work by name.
transition, backgroundTransition"slide", "fade"Reveal transitions.
controls, progress, hash, slideNumber, centertrue, true, true, false, falseReveal options with the same names.
margin, minScale, maxScale0.04, 0.2, 2How Reveal scales the slide to the window.
outDir, slidesDir, patternsDir, assetsDir"dist", "slides", "patterns", "assets"Folder names.
reveal{}Any other Reveal option, passed as it is. The starter uses display: "flex".

Commands

byeslide init [dir] [--template tour|report|lesson] [--force]
Creates a deck from a starter template, and asks which one when you leave out --template. --force writes into a folder that is not empty.
byeslide templates
Lists the starter templates.
byeslide build [dir] [--out dist] [--no-clean]
Writes the deck to dist/index.html with a local copy of Reveal.js and your assets.
byeslide preview [dir] [--host 127.0.0.1] [--port 4173] [--out dist]
Serves the deck, rebuilds on every change and reloads the browser.
byeslide check [dir] [--json] [--out dist] [--no-clean]
Opens each slide in Chromium and reports content that does not fit.
byeslide pdf [dir] [--output dist/<title>.pdf] [--out dist] [--no-clean]
Exports the print view to PDF.
byeslide bundle [dir] [--output dist/<title>.html] [--max-asset-mb 20] [--link-large-media] [--out dist] [--no-clean]
Writes the whole deck into one HTML file that opens offline.
byeslide patterns [dir]
Lists the pattern files.
byeslide install-browsers [chromium]
Installs the Chromium that check and pdf use.
byeslide --version
Prints the installed version.

A deck installs Byeslide as a dev dependency, so inside a deck run these commands as pnpm exec byeslide, or use the scripts in the starter's package.json: pnpm build, pnpm preview, pnpm check, pnpm pdf and pnpm bundle. pnpm pdf writes dist/deck.pdf.

Presenting and PDF

  • S Opens the speaker view: notes, a timer, the current slide and the next slide.
  • F Full screen. Esc shows all slides at once.
  • P In preview, writes dist/deck.pdf. In a static build, it opens the browser's print dialog.
  • Alt and click zooms into a detail. On Linux, use Ctrl and click.

Add ?view=scroll to the deck's URL to read it as one long page, or ?view=print for the print layout. To present in Teams, share the deck window and keep the speaker view on your own screen.

One-file bundle

byeslide bundle builds the deck, then puts every file it uses into one HTML file: stylesheets, fonts, images, scripts, ES modules, video, audio, and local iframes. The file opens from a download folder with no server and no network.

  • Media above --max-asset-mb (20 MB for each file by default) stops the command. The message names the file. Raise the limit, or use --link-large-media to keep a link to the file and send it along.
  • Every megabyte of video adds about 1.33 MB to the HTML file.
  • Files that a script loads while the deck runs, such as fetch("assets/data.json"), are not in the bundle. The command warns with the file and line.
  • Anything loaded from https:// still needs a network. The command warns about each one in HTML, CSS and module imports.

Use bundle when people should get the live presentation. Use pdf when they need a document to print or annotate.

Agent skills

Each deck has short instructions for AI agents in .codex/skills/. They point the agent at the right files instead of repeating what the files say.

byeslide-content
Updates slides from the files in content/, and keeps both in sync.
byeslide-author
Creates and edits slides from patterns.
byeslide-theme
Changes the look through the tokens in theme.css. Each new deck should get its own look.
byeslide-build
Builds, previews, checks and exports the deck.

Troubleshooting

check or pdf cannot find a browser
Run byeslide install-browsers.
Port 4173 is in use
preview tries the next ports and prints the address it uses.
Which version built this deck?
Built decks have a generator meta tag, and window.Byeslide.version returns the version.