PlainDeck Skill
Overview
PlainDeck is a Git-native, AI-friendly slide format backed by the plaindeck npm package (v0.6+). Projects are plain JSON: one file per slide, plus deck.json and theme.json at the root. Everything is readable, diffable, and editable via a JSON "operations" contract. The package ships a CLI, a TypeScript API, and renderers for standalone HTML, PNG, and PDF.
Recommended Agent workflow:
init → inspect → operations → validate → dry-run → apply → render
Environment Setup
Requires Node.js 22+. Check first, then install dependencies:
node --version # must be 22.x or newer
npm install plaindeck
# PNG/PDF rendering additionally requires Playwright Chromium:
npm install playwright
npx playwright install chromium
Run scripts/setup.sh for an idempotent environment check/install. If the user's project already has a deck.json, skip init.
Workflow
1. Initialize a project
npx plaindeck init ./my-deck --title "Make the idea visible" # default: showcase template, studio-cobalt theme
npx plaindeck init ./pitch --template pitch --theme night-citrus
npx plaindeck init ./paper-talk --template nature-methods # academic default (7 slides, light theme)
Templates: showcase (default, 5 slides), nature-methods (7-slide evidence-led methods talk), paper-reading (8-slide paper walkthrough), pitch, blank. Themes include studio-cobalt, night-citrus, ink-rose, paper-signal, night-blue, field-notes, editorial-blue, poster-red, nature-editorial.
init refuses to overwrite conflicting files (exit code 2) — always target a fresh or empty directory.
2. Inspect the project
Always inspect before editing so operations reference real slide paths and element IDs:
npx plaindeck inspect ./my-deck --json
3. Apply operations (the core editing mechanism)
All edits are declarative JSON operations using stable slide paths and element IDs — never array indices. Build an operations file (or pipe from stdin), preview with --dry-run, then apply:
cat changes.json | npx plaindeck apply ./my-deck --ops - --dry-run --json # preview: changedPaths + validation, no writes
npx plaindeck apply ./my-deck --ops changes.json --json # apply for real
Operation types: set-element, add-element, remove-element, move-element, add-slide, add-summary-slide, add-table-slide, duplicate-slide, rename-slide, move-slide, remove-slide, set-theme, set-slide-motion, set-footer.
See references/operations-reference.md for the full catalog with JSON examples. Rules: set-element cannot change id or type; move-* use before/after; invalid patches, duplicate element IDs, or deleting the last slide fail the entire batch. The whole batch is validated in memory before anything is written.
4. Validate
npx plaindeck validate ./my-deck --json
Exit codes: 0 success, 1 validation/execution failure, 2 argument error. With --json, stdout carries only JSON; diagnostics go to stderr.
5. Fast content additions (no hand-written JSON needed)
cat brief.md | npx plaindeck add-cards ./my-deck --content - --name "Weekly brief" --json # 1–8 cards from Markdown/JSON
npx plaindeck styles --search "editorial" # search 174 style recipes
cat brief.md | npx plaindeck add-cards ./my-deck --content - --style editorialMagazine --name "Brief"
cat benchmark.md | npx plaindeck add-table ./my-deck --data - --style rules --name "Benchmark" # Markdown/CSV/TSV/JSON → table slide
npx plaindeck add-slide ./my-deck --layout image-right --name "Results" # add a layout skeleton
Markdown cards format: # 主标题, ## 卡片标题, description, optional icon_name. Tables: first row = header; keep to ≤8 columns / ≤12 data rows; styles rules (academic, default), grid (parameter matrix), stripes (row comparison).
6. Render
npx plaindeck render ./my-deck --format html --output dist/deck.html # standalone web presentation (keyboard nav, progress, fullscreen)
npx plaindeck render ./my-deck --format png --output dist/slides # one PNG per slide: 001-name.png
npx plaindeck render ./my-deck --format pdf --output dist/deck.pdf # one page per slide, canvas-sized
- HTML embeds local images as data URIs — single self-contained file.
- External
http(s)images are blocked by default (replaced with placeholders). Pass--allow-networkonly for trusted projects. --slide <index|path>renders a single slide (index is 1-based).- PNG/PDF need Playwright Chromium. In headless/container environments, pass an existing Chromium via
browserExecutablein the TypeScript API.
TypeScript API (programmatic use)
import { applyOperations, createDeckTemplate, inspectDeck, loadDeck, renderPdf, renderPng, saveDeck, validateDeck } from 'plaindeck'
import { renderHtml } from 'plaindeck/render'
const deck = await loadDeck('./my-deck')
const inspection = inspectDeck(deck)
const result = applyOperations(deck, operations)
const validation = validateDeck(result.document)
if (!validation.valid) throw new Error(JSON.stringify(validation.issues))
await saveDeck('./my-deck', result.document, result.changedPaths)
const html = renderHtml(result.document)
await renderPng(result.document, { projectPath: './my-deck', output: './dist/slides' })
await renderPdf(result.document, { projectPath: './my-deck', output: './dist/deck.pdf' })
- Node-only filesystem/render APIs come from the package root;
plaindeck/renderis the browser-safe pure-HTML renderer. - Subpath entries:
plaindeck/core(schema, types, migrations, layouts, theme presets),plaindeck/react(React slide components),plaindeck/remotion(per-frame animation/video timeline; react + remotion are optional peer deps). - Static renderers (HTML/PNG/PDF/React) show the final layout and ignore animation; only
plaindeck/remotioninterpretsanimationandmotion.cameraframe data.
Project Format Essentials
my-deck/
├── deck.json # title, logical canvas, theme path, optional footer, slide order; must have "schemaVersion": "0.1"
├── theme.json # single source of truth for colors/fonts
├── theme.css # generated helper; do not hand-edit
├── slides/ # one JSON file per slide (e.g. 001-intro.json)
├── assets/ # local images (relative paths in slide JSON)
└── exports/ # rendered output (gitignore by convention)
Element types: text, image, rect, line, table. All frame coordinates are integers on a fixed logical canvas; off-canvas placement is allowed (elements can sit outside the visible area). Text/shape elements support optional fontFamily, textColor, fontSize, fontWeight, align, verticalAlign. Native tables: type: "table" with cells (2D string array), headerRows, columnWidths, alignments, style (rules/grid/stripes).
See references/project-format.md for the full spec.
Guidance for Agent-Generated Decks
- Inspect before editing: resolve real slide paths (
./slides/001-intro.json) and element IDs frominspectoutput; never guess or use indices. - Prefer add-cards / add-table for content slides: they parse Markdown/CSV/JSON into properly-styled, editable slides without hand-writing element JSON.
- Use dry-run before apply:
--dry-run --jsonreturnschangedPaths+ validation result at zero risk. - Validate after every batch and before rendering.
- Keep tables ≤8 columns / ≤12 rows for readability;
rulesfor academic,gridfor matrices,stripesfor comparisons. - Set document footers once with
set-footer(slide-name/date/page auto-update with reordering) instead of per-slide text elements. - Animation is optional metadata:
animation.entersupportsnone|fade|fade-up|fade-down|fade-left|fade-right|scale;motion.cameraadds a zoom. Timings are in frames (12 frames ≈ 0.5s at 24fps). Harmless for static output. - README content lives upstream: for anything beyond this reference, consult https://github.com/Mappedinfo/PlainDeck (docs/agent-api.md, docs/project-format.md) and
npx plaindeck --help.
Resources
references/cli-reference.md— full CLI command reference with exit codes and JSON-mode behaviorreferences/operations-reference.md— complete operations catalog with copy-paste JSON examplesreferences/project-format.md— deck.json / slide JSON / theme / animation field specificationscripts/setup.sh— idempotent Node 22+ + plaindeck + Playwright Chromium setup