Skip to content

Repository files navigation

decklet

Editable slide decks from any content, as one self-contained HTML file. A Claude Code and Codex skill with a plain-Node CLI: the deck is a JSON model, the file is the editor, and a verifier checks the layout before a human ever sees it.

Open-source alternative to PowerPoint, Keynote, Gamma and the PPTX-generator skills for coding agents. Next to frontend-slides-style HTML skills it adds in-place editing, an enforced brand type scale, an in-file PDF writer and a layout gate. Zero dependencies, zero network, MIT.

decklet demo: drag a row, page through slides that animate in, the inlined editor clips, the four anims, contact-sheet reorder, write a PDF

Try it live: https://grunion-ai.github.io/decklet/deck.html (drag, retype, ⊞ contact sheet, ⤓ PDF, F fullscreen). The template pack: https://grunion-ai.github.io/decklet/library.html — every template and layout the engine ships (58 + 22), one per slide, grouped by the kind of slide it is. If decklet builds you a deck, star the repo: stars are how agents and people find it.

What's next: ROADMAP.md covers speaker notes, mobile, document formats and export targets, with the sequencing and the rejected options.

Quickstart

Node ≥ 22, nothing to npm install. Install it as a skill, or clone it anywhere and call the CLI.

# Claude Code plugin (marketplace + plugin live in this repo)
claude plugin marketplace add grunion-ai/decklet
claude plugin install decklet@grunion

# Any skills-aware agent (Claude Code, Codex, Cursor, Amp, and the rest)
npx skills add grunion-ai/decklet

# Or by hand: SKILL.md is picked up on the next session
git clone https://github.com/grunion-ai/decklet ~/.claude/skills/decklet

Then, in any session: "make a deck from these notes".

# As a CLI
git clone https://github.com/grunion-ai/decklet && cd decklet
node bin/validate.mjs examples/explainer/model.json
node bin/create.mjs --model examples/explainer/model.json --out deck.html --title decklet
open deck.html

Works with Claude Code, Codex, Cursor and any agent that can run Node: the skill is SKILL.md, the toolchain is four Node scripts.

How decklet compares

decklet HTML slide skills (frontend-slides and kin) PPTX skills (python-pptx, html2pptx) Slidev, Marp Gamma and hosted generators
Output One .html, editable in place HTML page(s) .pptx Markdown source plus a build Hosted app
Edit after generation Drag, retype, resize, reorder, undo, all inside the file Regenerate (a fork adds drag editing) PowerPoint Edit the markdown, rebuild In the app
Brand type scale enforced Eight roles, no per-element size overrides, gate-checked Theme CSS Template Theme Themes
Layout checked before hand-off verify: parity, collisions, pixel diff against references No No automated gate No No
Runtime dependencies None None Python and libraries Node toolchain Docker or cloud
Network when opened None Webfonts, usually n/a Dev server for Slidev Yes
PDF Written inside the file, no dependencies Browser print Export Playwright or Chrome export Export

As of September 2026; check each project for current terms. Pick decklet when an agent drafts the deck and a person finishes it by hand. Pick a PPTX skill when the deliverable has to be a .pptx, and Slidev or Marp when the author writes markdown by hand.

What it is

A slide engine where the deck is a JSON model and the renderer is the editor. create turns model.json into one self-contained deck.html: open it from disk, drag and retype in place, present fullscreen, print to PDF. No install, no server, no network request, ever.

Who it is for. Agents (Claude Code, Codex, Cursor, any tool-using model) that must turn content into a deck a human will then edit. Humans get a file they can open and change; agents get a contract they can validate before a browser is involved.

Inputs → outputs.

  • in: any content (outline, notes, markdown, transcript, data) + a format (slides, carousel, document-letter, document-a4) + a style (brand tokens + eight text roles, or the neutral default)
  • out: deck.html — one file, ~40 KB (this repo's explainer carries three inlined screen clips, so it weighs ~270 KB), editable, printable, verifiable

Zero dependencies. The engine is plain HTML/CSS/JS in a single file. The CLI is plain Node ≥ 22. Playwright is an optional devDependency used only by verify, pdf and import-html; nspell + dictionary-en are optional devDependencies used only by create to flag misspellings (absent, create says so and the editor falls back to the browser's own checker).

One file. The model, the styles, the renderer and the editor ship inside the deck. Copy it, email it, commit it.

For agents

Read SKILL.md — it is the product. It defines the inputs, the process, the model and style contracts, verification thresholds, anti-patterns and three worked examples. The whole loop:

node bin/validate.mjs model.json                                   # contract check, no browser
node bin/create.mjs --model model.json --style style.json --out deck.html --format slides
node bin/verify.mjs deck.html [--refs shots/]                     # layout parity always; AE diff when refs exist
node bin/pdf.mjs deck.html [out.pdf]                              # vector PDF, one slide per page at slide size; self-gating
node bin/edits.mjs deck.html                                       # what the human changed in the editor (read before revising)
node bin/create.mjs --model model.json --out deck.html --from deck.html   # revise: keep ids, replay human edits (human wins), keep versions
node bin/import-html.mjs --w 1600 --h 900 --out model.json 'pages/*.html'   # finished HTML → model

llms.txt is the machine summary and file map. deck.html is the engine explaining itself — twelve slides built from examples/explainer/model.json by the same CLI, including the motion vocabulary and three GIF clips of the editor filmed from the deck itself.

Guarantees

  • Single file. Model + renderer + editor in one .html; nothing is fetched at runtime.
  • Zero network. No webfonts, CDNs or remote images; images are data: URIs. The gate greps for it.
  • Editable. Drag, ⌘-multi-select, marquee select (drag a window on empty canvas), double-click to retype, corner-nib resize, point nibs on connectors, floating role/mark/colour toolbar (B/I/U/S, sub/sup, the deck's own swatches; ⌘B/⌘I/⌘U), undo that survives reload, contact sheet with grab-and-drag reordering.
  • Human edits are never lost. Every edit lands in an in-file log and, with ⌘S in Chrome/Edge, in the deck file itself (File System Access — asked for once). create --from replays the log onto the next version, human wins, conflicts flagged; the file keeps a version history you can restore from. bin/edits.mjs prints the log for an agent.
  • Motion, honestly. Four entrance anims — rise, fade, pop, wipe — staggered 120 ms on slide entry only. prefers-reduced-motion turns them off, and print, the contact sheet, the PDF and verify all draw the settled frame, so motion can never change what is measured or exported.
  • Brand-true. Eight text roles (Title, Supertitle, H1, H2, Body, Caption, Label, Stat) are the only source of font/size/leading; rows cannot override them. Chrome is one deck-wide master layer on a margin token. Tokens re-theme every deck.
  • PDF. writes a true slide-sized PDF inside the file (foreignObject → canvas → JPEG → PDF, zero dependencies); ⌘P is the paper path with named Letter/A4 pages (Safari-safe), one page per slide. Safari's in-file raster path is unconfirmed — it falls back to print.
  • Verified. validate (pure Node) + verify (layout parity in a real browser, AE pixel diff against references). A deck that fails parity is not done.

Model snippet

{
  "w": 960, "h": 540,
  "layouts": { "content": { "supertitle": { "x": 60, "y": 52, "w": 840, "role": "Supertitle" },
                            "title":      { "x": 60, "y": 76, "w": 840, "role": "H1" } } },
  "master": [ { "id": "foot", "footer": 1, "x": 660, "y": 500, "w": 240, "align": "right", "role": "Label", "text": "decklet" } ],
  "slides": [ { "layout": "content", "els": [
    { "slot": "supertitle", "text": "THE MODEL" },
    { "slot": "title", "text": "Every slide is rows in a JSON array." },
    { "x": 60, "y": 170, "w": 195, "h": 110, "tile": 1, "role": "Stat", "text": "1,240" },
    { "x": 120, "y": 340, "w": 70, "h": 60, "bg": "#2F4E7A", "bar": 1 },
    { "x": 730, "y": 200, "w": 150, "donut": 72 }
  ] } ]
}

A row is text by default; box, tile, bar, line, donut, svg, img are props on the same row. Roles come from styles.roles (or style.json); a row may set weight/colour/case, never size. Full reference: SKILL.md → MODEL CONTRACT.

Feature matrix

capability status notes
slides 16:9 (960×540, 1600×900) supported editing, contact sheet, present, PDF, verify
carousel 1:1 / carousel-4x5 experimental sizing, editing, PDF work; no per-card PNG export
document-letter / document-a4 experimental page = canvas, print zoom 1; text does not flow across pages
drag / multi-select / resize / undo supported undo history persisted per deck; connectors get point nibs
edit log · write-back · versions supported in-file /*LOG*/ + /*VERSIONS*/; ⌘S writes the file (Chrome/Edge), create --from migrates, restore from the history popover
inline text editing + B/I/U/S + colour runs supported stored as html on the row
roles · slots · master layer · footer counter supported see SKILL.md
bars, lines, donuts, tiles, boxes supported one row each, no SVG layer
SVG / raster images supported inline svg, data: img
entrance motion supported anim: rise|fade|pop|wipe, 120 ms stagger on slide entry, respects reduced-motion, never in print/PDF/parity
animated GIF clips supported img data: URI plays as-is; docs/record-clips.mjs films them from the deck and writes them back into the model
contact sheet (select, reorder, dup, delete) supported 3-across live thumbnails; pointer-drag reorder (mouse + touch), also in present mode
fullscreen presentation supported F / ⛶, hover-peek HUD (pinned while a menu or the sheet is open)
PDF supported ⤓ → slide-sized PDF written in-file (Chromium verified; Safari unconfirmed → print fallback); ⌘P → paper, Letter/A4 named sizes
HTML pages → model supported bin/import-html.mjs (Playwright)
validate / verify supported parity mandatory, AE optional
PPTX / Google Slides export no out of scope
presenter view, notes roadmap

Repo map

deck.html            the engine + the explainer deck (built from examples/explainer)
template.html        the engine with an empty model — create.mjs fills it
bin/validate.mjs     model contract, pure Node
bin/create.mjs       model (+style) → deck.html; format presets
bin/verify.mjs       parity + AE + contract proof (Playwright optional)
bin/import-html.mjs  finished HTML pages → model.json (Playwright)
SKILL.md             the agent authoring skill
llms.txt             machine summary
examples/            explainer, quarterly-update, launch-carousel, one-pager (brief → model + style)
test/gate.test.mjs   engine + validator + create + import + live proofs

Test

npm test            # node --test; live browser tests skip when Playwright is absent (CI installs Chromium, so they run there)
npm run test:live   # same, after: npm i -D playwright && npx playwright install chromium

Roadmap

Full plan, with sequencing, sizes and rejected options: ROADMAP.md.

Now: contract hygiene, the slide.notes and row.alt model fields, notes as data, phone reading, new format presets, a PNG export CLI. Next: presenter view, searchable PDF, aspect-aware layouts, phone presenting. Later: document text flow, PPTX export, touch editing, a slide revision store.

License

MIT © Grunion

About

AI slide generator for coding agents: a Claude Code and Codex skill plus CLI that turns any content into one self-contained, hand-editable HTML slide deck (single file presentation, zero dependencies): brand-true type roles, drag-and-retype editor, in-file PDF, verified layout. Open-source alternative to PowerPoint, Gamma, Slidev and PPTX skills.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages