Skip to the presentation
Press F or Present to start. ↑ ↓ change slides; ← → move through the active carousel, or change slides when there is none.

slidepig: decks that are web pages

This page is a slide deck.

Scroll it like an article, or press F (or Present, bottom left) to give it as a talk. Same page, same URL, same content.

It is built with slidepig, and it explains what slidepig is for.

01

slidepig

Write a deck once. Read it, or present it.

slidepig is a small React library that turns typed slide data into a single web page. Visitors scroll it like an article. Presenters press F and the same page becomes a full-screen slideshow.

No export step, no PDF, no second copy that drifts out of date. The link you send before the meeting is the deck you present in it.

02

The problem

Slide files are bad web pages. Web pages are bad slides.

A pitch usually lives twice: as slides for the meeting and as a PDF or doc for everyone who missed it. The PDF cannot play a video, cannot be read on a phone, and nobody can link to page seven.

A web page fixes all of that, until you try to present it. Scrolling in front of an audience is clumsy, and nothing tells you where one idea ends.

slidepig keeps the page and adds the missing mode. Every slide is a section with its own URL, and presenting is just a different way of showing the same sections.

Reading and presenting share one DOM
03

The model

Your deck is data. The library is the stage.

You describe slides as plain objects: an id, a title, some paragraphs, a layout, and the media they show. defineDeck infers every media id, theme and background name, so a typo is a type error instead of a blank square on stage.

<Deck> renders them. Layouts cover the shapes a pitch needs: hero, story, rows, timeline, metric, case, groups, statement and closing. Code listings like this one are built in. When nothing fits, pass any React node as a slide's visual, or take over the slide entirely with render.

deck.ts
import { defineDeck } from "slidepig";

export default defineDeck({
  title: "Our seed round",
  backgrounds: {
    night: { src: "/art/night.jpg" },
  },
  slides: [
    {
      id: "hello",
      layout: "hero",
      tone: "dark",
      background: "night",
      title: "Write it once.",
      body: ["Read it, or present it."],
    },
  ],
});
04

Proof, not promises

Extracted from decks that already shipped.

slidepig did not start as a framework. It is the part two real pitch decks turned out to share, pulled out once the second deck proved which parts were mechanics and which were content.

2pitch decks it was extracted from
−89%image weight on the first deck after the asset pipeline
0runtime dependencies beyond React
05

Benefits

Better for everyone in the room, and everyone who wasn't.

The same page serves three people: the reader who opens the link alone, the presenter on stage, and the author who has to change slide six an hour before the meeting.

For the audience

  • Every slide has a link

    Share #numbers and it opens on that slide, in either mode.

  • Reads on a phone

    Reading mode is a responsive article, not a shrunken slide.

  • Accessible by default

    Real headings, skip link, focus management, labelled controls, reduced motion.

For the presenter

  • Keyboard first

    F presents, ↑ ↓ change slides, Esc returns to reading.

  • Media that cooperates

    ← → drive the active carousel; Space plays the slide's video.

  • Next slide is ready

    Images for the next slide are fetched and decoded before you advance.

For the author

  • Typed content

    Slides are data with inferred names, checked at build time.

  • Live visual tuner

    Adjust backgrounds and colors in the browser, copy the result back to code.

  • Optimized images

    AVIF and WebP derivatives, blur placeholders, preload hints.

06

Media that behaves

Carousels, lightboxes and video, wired to the presenter.

Name media once in a registry and reference it by id from any slide. Images open in a lightbox; groups become a carousel the arrow keys control while presenting.

Missing files are not errors. A media entry without a src renders a labelled placeholder, so a draft deck never looks broken, it just looks unfinished.

What a missing file looks like

The entry below has a title and a description but no src yet. It renders as a labelled slot, so reviewers see what is planned rather than a broken player.

07

Design in the browser

Tune the look live, then hand the result to your editor.

Press D to open the tuner on every slide. Swap backgrounds, pick a theme, drag the overlay opacity, try accent colors, and see them applied as you go.

Copy the settings and you get a ready-to-paste snippet that names the slide, which also makes a precise prompt for a coding agent. The tuner never writes files, and by default it only exists on localhost.

08

Package boundary

slidepig owns the mechanics. You own the deck.

The library never scans your DOM or guesses at your content. It handles navigation, presenting, preloading, media behavior and the chrome around slides. Everything that makes a deck yours stays in your repository.

What lives where

slidepig
Hash navigation, keyboard and fullscreen, preloading, controls, layouts, lightbox and carousel, the tuner. No dependencies.
slidepig/site and slidepig/assets
Optional build tooling in the same package: prerendered sites, validation, a Worker, and AVIF/WebP derivatives.
Your deck
Copy, media registry, themes and backgrounds, custom visuals, and any CSS you want to override.
Use only the parts you need

One package, imported by path. slidepig/react exports the headless useSlideshow hook and SlideshowControls for a fully custom renderer. slidepig/core has the framework-free navigation and preload helpers. Build tools such as sharp are optional peers, so a page that embeds one deck installs nothing else.

09

Three steps

From an empty folder to a deck you can present.

slidepig works in any React app: Vite, Next.js, TanStack Start, Remix. Every slide is in the rendered HTML, so server rendering and static export work without extra setup.

  1. 01 · Install

    npm i slidepig

    Import slidepig/styles.css once. React 18 or 19 is the only peer dependency.

  2. 02 · Write

    defineDeck({ … })

    Slides, media and themes as typed data, in one file you can review in a pull request.

  3. 03 · Render

    <Deck deck={deck} />

    Deploy it like any page. Press F when it is your turn to speak.

10

That was the demo

You just read a deck. Now press F and present it.

Everything on this page came from one data file and one component. Open the source of this demo next to it, and change a title, to see how little stands between an idea and a deck.