ring:deck

Installation
SKILL.md

ring:deck — Lerian Editorial Deck Scaffolder

Scaffold a self-contained Node project for a Lerian-branded HTML presentation. Every deck ships with a live-reload dev server, a presenter view designed for a second screen, a phone-as-remote over WebSocket, and Puppeteer-driven PDF export. The output is a working local project the user runs themselves — not a single HTML file, not a hosted site.

When to use this skill

Use whenever the user asks for a branded slide deliverable: board deck, investor update, conference talk, all-hands, customer pitch, internal review. The trigger is "deck-shaped output" — sequenced sections, speaker notes, something a human will present live.

  • "Make me a board deck for Q2"
  • "Build an investor deck for the Series A conversation"
  • "I need a conference talk deck"
  • "Scaffold a new presentation for next week's all-hands"
  • "New slide deck for the product review"

When NOT to use this skill

  • Editing an already-scaffolded deck — edit deck.html inside that project directly. The scaffold is a one-shot bootstrap, not an editor.
  • Non-presentational documents — memos, one-pagers, exec emails, PR descriptions. These are written content, not sequenced slides.
  • Single static HTML visualization — a diagram, dashboard, or comparison table is ring:visualize. That skill produces one .html file; this skill produces a Node project.

Inviolable vs Creative

Inviolable (engineering + brand). Canvas dimensions, flex layout, pagination, overflow, export pipeline — see engineering.md. Brand colors, typography, logo — see brand.md. These MUST NOT bend.

Creative (the canvas itself). Slide composition, narrative arc, headline voice, content rhythm, layout imagination. Use the primitives; the composition is yours.

Two Lerian Design Systems Side by Side

HARD GATE (brand). ring:deck uses editorial tokens (Amarelo #FEED02, Poppins + IBM Plex Serif, JetBrains Mono) intentionally separate from ring:visualize's product-console tokens (#FDCB28 sunglow, Inter). Both systems are canonical Lerian. MUST NOT cross-mix tokens. A deck with ring:visualize's Inter + sunglow is wrong; a diagram with ring:deck's Poppins + Amarelo is wrong. Keep the systems pure.

Mandatory Reading — HARD GATE

Before writing any slide content, MUST read:

  1. references/brand.md — colors, typography, logo (inviolable)
  2. references/engineering.md — canvas, flex, pagination, 24px text floor, overflow (inviolable)
  3. references/primitives.md — the CSS atoms available: eyebrow, pill, kpi, ticks, numbered, table.grid, dashed-hairline, narrative-arc, transition-column, org-node-flag, dual-sided-argument, inline-mini-legend
  4. references/chart-primitives.md — stacked-horizontal-bar, vertical-bar-chart, 2x2-matrix, funnel (+ monetary overlay), inline-micro-chart
  5. references/speaker-notes.md — JSON schema + presenter voice

Server + export references (read when tooling questions come up):

  1. references/server.md — dev server, WebSocket protocol, port override, trust model
  2. references/export.md — Puppeteer PDF export flow

Skipping the engineering and brand files is the #1 failure mode — they encode the canvas physics and brand rigor that every deck must obey.

Skill Workflow

Phase 1: Gather minimum-viable requirements

MUST ask the user (skip questions already answered):

  1. Deck title — e.g., "Lerian Board Meeting Q2 2026"
  2. Audience — board, investors, conference, team, external partner
  3. Rough slide count — e.g., around 15
  4. Directory name — defaults to kebab-cased title

MUST NOT ask about: tokens, fonts, layout, runtime, export. Those are fixed by the skill — asking is validation theater.

Phase 2: Read mandatory references

See Mandatory Reading above. HARD GATE — MUST NOT write slides without reading refs 1-5.

Phase 3: Scaffold project

Sanitize substitution variables first. Before copying any template, compute:

  • DECK_TITLE = the user-supplied title verbatim (e.g., "Q2 2026 Board Deck"). Used inside HTML text nodes — HTML-escape <, >, & if the title contains them.
  • DECK_NAME = DECK_TITLE.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, ''). MUST be kebab-case — it's the project directory name AND the "name" field in package.json, which rejects spaces, quotes, and most punctuation. Example: "Q2 2026 Board Deck" → "q2-2026-board-deck".
  • YEAR = current 4-digit year.
  • COPYRIGHT_HOLDER = "Lerian Studio" unless the user specifies otherwise.

Naive str.replace on an unsanitized title breaks package.json (quotes, newlines) and fails filesystem validation. Sanitize first, substitute second.

Then create <DECK_NAME>/ directory with these files (copy from the skill's templates/, assets/, and scripts/ directories):

Source (skill) Destination (scaffolded deck)
templates/deck.html deck.html (substitute {{DECK_TITLE}})
templates/presenter.html presenter.html
templates/remote.html remote.html
templates/package.json.tmpl package.json (substitute {{DECK_NAME}})
assets/* assets/*
scripts/* scripts/*
templates/LICENSE.tmpl LICENSE (substitute {{YEAR}}, {{COPYRIGHT_HOLDER}} — default Lerian Studio)
templates/README.md.tmpl README.md (substitute {{DECK_TITLE}}, {{DECK_NAME}})
templates/.gitignore.tmpl .gitignore (no substitution)

Phase 4: Compose slides in deck.html

Compose slides from the brand tokens and primitives to serve the deck's narrative. There is no required slide menu — use a cover when it serves the moment, a full-bleed accent slide when the message demands it, invent a layout when the content calls for something the primitives don't anticipate. The engineering and brand constraints are hard; the composition is yours.

For each slide:

  1. Compose using primitives from references/primitives.md (and charts from references/chart-primitives.md where they fit)
  2. Borrow from the example slide templates in templates/slide-*.html when a composition there already fits — those are examples, not a required menu
  3. Replace any placeholder content with actual content
  4. Obey references/engineering.md (flex: 1, min-height: 0, no fixed-height cards, 24px text floor, overflow hidden)
  5. Obey references/brand.md (tokens, typography, logo)

Phase 5: Write speaker notes

  • Flat JSON array of strings
  • One entry per <section>, zero-indexed matching <section> order
  • \n\n for paragraph breaks
  • Speaking voice (not written voice) — concrete data first, then context
  • See references/speaker-notes.md for full guidance

Phase 6: Hand off to user

Print the Handoff Message Template (below). Do NOT run pnpm install or pnpm dev for the user — the deck is theirs to run.

Anti-Rationalization Table

Rationalization Why It's WRONG Required Action
"Content is simple, I can skip engineering.md" Simple content still breaks with fixed-height cards. Skipping the canvas rules is the #1 failure mode. MUST read engineering.md
"I'll pick colors that look nicer than Amarelo" #FEED02 Amarelo is Lerian brand primary, not a style choice. Swapping is a rebrand, not a tweak. MUST use tokens from brand.md
"I can skip speaker notes" Notes surface in presenter view — presenters rely on them. Empty notes = unusable presenter view. MUST write notes for every slide
"Deck already has fonts — I'll skip the Google Fonts block" Every scaffolded deck is self-contained. The fonts block in deck.html is mandatory. MUST preserve the Google Fonts import block
"I'll use Chart.js for richer charts" v1 is pure CSS/HTML. Chart.js is v2 work. MUST use only the 4 chart primitives
"I'll mix deck tokens and visualize tokens" Editorial and product-console design systems are deliberately separate. MUST keep deck tokens pure
"I'll hardcode the slide count in pagination" <section> count is dynamic. deck-stage.js fills pagination at runtime. MUST use <span class="page-num"> + <span class="page-total"> pattern
"Puppeteer install is slow — I'll skip it" Export is a first-class feature. Install is a one-time cost. MUST include puppeteer in package.json
"Reading the reference summary in this SKILL.md is enough" Summaries are lossy. Token values, exact class names, and pattern structure live in the reference files. MUST use the Read tool to open each reference file

Pressure Resistance

User Says Your Response
"Just make a simple HTML file, no Node project" "Cannot: dev server + presenter + remote + export require Node. If you want a single static HTML without tooling, use ring:visualize instead — different skill, different purpose."
"Skip the presenter view, I don't need it" "Generated anyway — costs nothing, adds value if needed later. Zero-config removal: just don't open the /presenter URL."
"Use Inter instead of Poppins" "Cannot: #FEED02 Amarelo + Poppins + IBM Plex Serif is Lerian editorial brand. For Inter/sunglow tokens, use ring:visualize."
"Skip the license file" "Cannot: Lerian open-source commitment is a third rail. Apache 2.0 license ships with every scaffold."
"Don't watch files, just write the deck once" "Cannot: dev server + chokidar is the scaffold default. For a static export, run pnpm export and distribute the PDF."
"Host the deck online" "Out of scope. Scaffolded deck is local-network. Hosting is the user's choice — any static host (Vercel, Cloudflare Pages) serves deck.html + assets/ + scripts/ (minus dev-server.mjs). Document if the user asks."
"Build me a timeline/quote/org-chart slide" "Compose one from the primitives in primitives.md — eyebrow, pill, kpi, ticks, narrative-arc, transition-column, and friends are enough for most shapes. If a specific shape (e.g., image-hero, photo-grid) needs primitives that don't exist yet, flag as v2 and proceed with the closest composition."

Blocker Criteria — STOP and Report

STOP and report to the user if:

Decision Type Blocker Condition Required Action
Missing Runtime Node not installed, or Node version < 18.0.0 STOP — user must install Node 18+ before proceeding
Directory Collision Target directory exists and is non-empty STOP and ask: overwrite, rename, or cancel
Unsupported Export User asks for editable-PowerPoint PPTX (text + shapes, not screenshots) STOP — report v1 PPTX is screenshots mode only (PNG per slide + speaker notes via addNotes()); editable PPTX is deferred because CSS layout doesn't map cleanly to PowerPoint shapes. Offer: PDF + re-author manually, or accept screenshots-mode PPTX.
Theme Customization User asks for accent override, density toggle, font swap STOP — report v1 is locked to Lerian editorial tokens; customization is v2
Auth on Remote User asks for PIN or auth on the remote control STOP — report v1 is local-network trust model; PIN auth is v2

HARD BLOCK — cannot proceed:

  • If the skill's references/ directory is missing any mandatory file (any of the 7 refs) → report which is missing; instruct user to re-clone the plugin repo.
  • If the skill's templates/ is missing deck.html or the example slide templates → same remediation.

Severity Calibration

Severity Examples Action
CRITICAL Fixed-height cards used; hardcoded pagination NN/17; wrong color tokens; wrong fonts MUST fix before completing
HIGH Text smaller than 24px floor; chart without aria-label; speaker notes missing SHOULD fix; warn user if shipping as-is
MEDIUM Placeholder content not replaced; content-accent slides used so often they lose impact Warn user; user decides
LOW Minor typography drift (e.g., 80px hero where 96px would fit) Mention; user decides

Cannot Be Overridden (Non-Negotiable)

  • Lerian brand tokens — Amarelo #FEED02, Poppins + IBM Plex Serif, JetBrains Mono
  • Apache 2.0 license on scaffolded deck
  • Dynamic pagination via <span class="page-num"> + <span class="page-total"> (two documented exceptions: appendix letter pagination A1 / 8 and main-deck companion letter-suffix 09b / 14 — both hardcoded without the .page-num class so the runtime leaves them alone)
  • flex: 1; min-height: 0 on main content grids (engineering.md HARD GATE)
  • Speaker-notes JSON structure — flat array of strings
  • WebSocket protocol — 5 message types (nav, blank, state, hello, reload) in v1. state and nav carry a total field so the remote can render N / M once the main deck has announced totals. See references/server.md for the full protocol.
  • Self-contained scaffold — every deck is an independent Node project; no shared workspace dependency

Known Limitations (v1)

  • Remote shows N / ? for slide-total until the first nav event fires. Server doesn't know total until main deck broadcasts. Fine for most flows; users rarely notice.
  • No auth on remote — local network trust model. Document in handoff.
  • Puppeteer bundled Chromium weighs ~200MB per scaffolded deck. pnpm export:chrome uses system Chrome instead.
  • Google Fonts online dependency — scaffolded deck fetches fonts from Google CDN. Offline presentations need a pre-cached browser.

Handoff Message Template

After scaffolding, print this to the user:

Deck scaffolded at: ./<deck-name>/

Next steps:
  cd <deck-name>
  npm start                 # one command: installs deps if needed, boots
                            # dev server on http://localhost:7007, and
                            # auto-opens the deck in your default browser.
                            # (Suppress the auto-open with AUTO_OPEN=false.)

During the presentation:
  - Main deck:   http://localhost:7007
  - Presenter:   http://localhost:7007/presenter  (open on second screen)
  - Remote:      http://<LAN-IP>:7007/remote      (open on phone, same Wi-Fi)

In-browser toolbar (floating, bottom-center):
  Tweak      capture feedback on the active slide — appended to
             feedback.jsonl. Tell Claude "check tweaks" to review.
  Presenter  opens /presenter in a new window
  PDF        triggers Puppeteer export, streams deck.pdf for download
  PPTX       same flow for deck.pptx (screenshots + speaker notes)
  Remote     shows the LAN URL for the phone remote

Keyboard controls (main deck):
  →/Space  next slide
  ←        previous slide
  F        fullscreen
  S        toggle speaker notes overlay
  G        go to slide number
  B        blank screen
  T        toggle tweak panel
  H        toggle toolbar visibility

Export from the terminal (optional — the toolbar buttons are easier):
  npm run export            # PDF via bundled Chromium (~200MB first time)
  npm run export:chrome     # PDF via system Chrome (~50MB, faster)
  npm run export:pptx       # PPTX (screenshots + notes, not editable)

Local network only — no auth. Don't expose port 7007 publicly.

Future Work (v2 Candidates)

  • Editable PPTX export (text + shapes mapped from CSS layout, not screenshots) — v1 ships screenshots mode only
  • Data-driven mode: YAML/JSON content files + template binding
  • Theme customization: accent override, density toggle
  • Additional primitives: timeline, quote block, org-chart, image-hero, photo-grid
  • Remote auth: short-lived rotating PIN displayed on main screen
  • Chart.js opt-in for richer analytics
  • Self-contained HTML bundle export (no-CDN offline package)
  • Multi-deck workspace (shared deps)
Related skills
Installs
1
GitHub Stars
180
First Seen
9 days ago