Dependency-free, animated presentation slides that run entirely in your terminal.
bareslides renders slides into an in-memory cell buffer, emits 24-bit truecolor ANSI, and does flicker-free frame-diffed updates — so you get smooth transitions, progressive build-ins, and even a live command that runs on stage, all from a single TypeScript file. No browser, no export, no runtime dependencies beyond a TypeScript loader.
┌───────────────────────────────────────────────────────────┐
│ │
│ ██████ █████ ██████ ███████ ... │
│ │
│ slides that live in your terminal │
│ │
│ ▮ 01/09 ● · · · · · · · · arrows move q quit │
└───────────────────────────────────────────────────────────┘
- It's just code. A deck is a TypeScript array of slides. If you can write a function, you can write a slide — and drop to raw drawing whenever you want.
- Live, offline, fast. Your diffs, logs, and commands already live in the terminal. Run one on a slide (with a baked fallback so it never fails on stage).
- No dependencies. The renderer is hand-rolled: a cell buffer, ANSI escapes,
a bitmap title font, and deterministic transitions. Nothing to
npm audit.
Slides are real terminal frames. Here's a deck rendered straight from the cell buffer to SVG — no screenshots, no recording tool. The animations below are plain looping SVGs, so they play right here on GitHub.
A coverSlide — the block-glyph banner font, subtitle, and footer.
A bulletSlide — bullets build in one at a time, with an emphasized line.
Everything is a deterministic function of a frame counter, so animation is
reproducible — and exportable. The pipeline diagram loops off ctx.frame; the
transition is a pure (from, to, t):
A frame-indexed diagramSlide — a token loops through the pipeline.
The dissolve transition resolving into a bullet slide.
These are generated with npm run gallery. Export any slide of
any deck yourself — still or looping animation — with
npm run render:svg.
git clone <your-fork-url> bareslides
cd bareslides
npm install
npm start # runs the feature tourOr point it at any deck file:
npx bareslides examples/hello-world.ts
npx bareslides examples/feature-tour.ts --offlineCreate my-deck.ts:
import { defineDeck, coverSlide, bulletSlide, onelinerSlide } from "bareslides";
export default defineDeck({
title: "My Talk",
slides: [
coverSlide({
id: "cover",
title: "BARESLIDES",
subtitle: "slides in your terminal",
footer: "Your Name @yourhandle",
enter: "type",
}),
bulletSlide({
id: "why",
title: "Why terminal slides?",
bullets: ["No browser", "Live commands", "Just code"],
note: "The one thing to remember.",
enter: "dissolve",
}),
onelinerSlide({ id: "end", text: "Thanks!", enter: "glitch" }),
],
});Run it:
npx bareslides my-deck.tsWorking inside this repo instead of installing the package? Import from
../src/index.js(see the files inexamples/).
| Builder | What it makes |
|---|---|
coverSlide |
Big block-glyph title banner with subtitle + footer |
sectionSlide |
A section divider (kicker + centered title) |
bulletSlide |
A list whose bullets build in one at a time, with an optional emphasized note |
onelinerSlide |
One large centered sentence |
diagramSlide |
A freeform draw(screen, rect, frame) region — the animation escape hatch |
commandSlide |
Runs a real command live and types out its output, with a baked fallback |
Need something the builders don't cover? A slide is just an object with a
render(screen, ctx) method — pass your own and draw directly. See
docs/slide-model.md.
Set enter on any slide to the transition played when you navigate to it:
cut, dissolve, wipe, glitch, scan, type. All are deterministic.
| Keys | Action |
|---|---|
→ space n l |
Next slide |
← p b h |
Previous slide |
g |
Slide map (overview); enter jumps, g/esc closes |
digits then enter |
Jump to a slide number |
r |
Replay the current slide's animation |
s |
Toggle CRT scanlines |
f |
Command slide: force the baked fallback |
enter |
Command slide: re-run the command |
q / Ctrl-C |
Quit (restores the terminal) |
Full reference: docs/keybindings.md.
bareslides <deck.ts> [--offline] [--no-scanlines] [--start N] [--fps N]
--offline— command slides show baked output; nothing is spawned.--no-scanlines— start with the CRT overlay off.--start N— open on slide N (1-based).--fps N— animation speed (8..60, default 20).
No TTY handy? Render any slide to a standalone SVG — a still or a looping animation — with the dependency-free exporter (this is how the Gallery above is made):
npm run render:svg <deck.ts> <slide|index|all> [flags] [w] [h]
# a still, wrapped in terminal-window chrome
npm run render:svg examples/feature-tour.ts cover --chrome -o cover.svg
# a looping animation of the slide's own frame clock
npm run render:svg examples/feature-tour.ts pipeline --anim -o pipeline.svg
# a looping transition INTO a slide, from the slide before it
npm run render:svg examples/feature-tour.ts bullets --transition dissolve -o t.svgKey flags: --anim, --transition <name>, --frames N, --fps N, --chrome,
--scanlines, -o <file>. Output is deterministic, so the SVGs diff cleanly.
- Authoring guide — build a deck end to end.
- The slide model —
Slide/SlideCtx/Deck, the stage, the frame clock. - Builder reference — every builder and its options.
- Animation — writing deterministic frame-indexed animations.
- Command slides — live commands and baked fallbacks.
- Keybindings.
This repo ships a .claude/ folder so Claude Code
can help you author decks:
/new-deck— scaffold a new deck from the template./new-slide— add a slide to an existing deck.- Skills
create-deckanddesign-slideteach Claude the slide model and design conventions.
npm run typecheck # tsc --noEmit (strict)
npm test # node:test suite (engine + builders + examples + svg export)
npm run render examples/feature-tour.ts all # headless plain-text render
npm run gallery # regenerate the README's SVG preview assetsMarkdown authoring, in-terminal sixel/inline-image rendering, PDF export, a speaker-notes second screen, and publishing to npm. (SVG export of slides already works — see Exporting slides as images.) Contributions welcome — see CONTRIBUTING.md.
MIT.