{"slug": "show-hn-whitedeck-black-on-white-keynote-like-slides-claude-skill", "title": "Show HN: Whitedeck – Black on White Keynote Like Slides Claude Skill", "summary": "Developer franzenzenhofer released whitedeck, an open-source Claude Code skill and CLI that converts markdown into Apple Keynote-style white-theme slides in HTML, PDF, editable PPTX and native .key formats. Whitedeck extracts every placeholder position, size, font and point size from Apple's own Keynote export into a single source of truth (src/theme/white.json) and asserts that geometry with integration tests across every output format. The tool runs on macOS, Linux and Windows with Node.js 20 or newer, requires Keynote.app only for .key output, and installs via npm from the project's GitHub tarball.", "body_md": "**The content is the design.** whitedeck turns markdown into slides in Apple Keynote's plain\nWhite theme: HTML, PDF, editable PPTX and native `.key`, with Apple's own layout geometry.\nBuilt for Claude Code and other AI agents, so their decks stop looking like AI decks.\n\n```\nnpm install -g https://github.com/franzenzenhofer/whitedeck/archive/refs/heads/main.tar.gz\nwhitedeck init my-deck.md\nwhitedeck build my-deck.md -f all\n```\n\nAsk an AI agent for slides and it decorates: gradients, glow, emoji for icons, a card around every bullet, a headline that names a topic instead of making a point. It looks busy and says little.\n\nwhitedeck takes all of that off the table. White canvas, one typeface, one claim per headline, the evidence on the slide and its source underneath. There is nothing to fiddle with, so the only thing left to improve is the argument. Pretty slides are a sign of the wrong priorities.\n\nSame four facts on both slides. One wants to be admired, the other gets read.\n\nUnder the plain look sits **provably exact geometry**: every placeholder position, size, font and\npoint size is extracted from Apple's own Keynote export into one source of truth\n(`src/theme/white.json`) and asserted by integration tests in every output format.\n\nEvery image below is a page of [`docs/showcase/showcase.md`](https://github.com/franzenzenhofer/whitedeck/blob/main/docs/showcase/showcase.md), rendered by\n`whitedeck build showcase.md -f pdf`.\n\n|  `title` |  `title-bullets` | \n|  `compare` |  `photo-horizontal` | \n|  `title-center` |  `title-bullets-photo` | \n|  `bullets` |  `quote` | \n\n| Format | Engine | Notes | \n|---|---|---|\n| `html` | [Marp CLI](https://github.com/marp-team/marp-cli) + generated Keynote-exact CSS theme | self-contained file | \n| `pdf` | same render, printed via headless Chrome | one 16:9 page per slide | \n| `pptx` | [PptxGenJS](https://github.com/gitbrent/PptxGenJS) , native OOXML | fully **editable** , exact EMU geometry | \n| `key` | the pptx, imported and saved by the real Keynote.app, then reopened and checked | the verified pptx: clickable links, no theme dummy copy; the build throws on either (macOS only) | \n\nwhitedeck runs on macOS, Linux and Windows with Node.js 20 or newer. No Keynote and no\nPowerPoint needed for anything but `.key`.\n\n```\nnpm install -g https://github.com/franzenzenhofer/whitedeck/archive/refs/heads/main.tar.gz\nwhitedeck init my-deck.md\nwhitedeck build my-deck.md -f all\n```\n\nThe commands are the same in Terminal, bash, PowerShell and cmd.\n\n| format | needs | macOS | Linux | Windows | \n|---|---|---|---|---|\n| `pptx` | nothing - PptxGenJS writes the file, no PowerPoint | yes | yes | yes | \n| `html` | nothing - Marp renders it without a browser | yes | yes | yes | \n| `pdf` | a Chromium-family browser: Chrome, Chromium or Edge | yes | yes | yes, Edge ships with Windows | \n| `key` | Keynote.app (found by bundle id `com.apple.Keynote` ) | yes | no | no | \n\n**`-f all` builds every format this machine can build**: html + pdf + pptx (+ key on a Mac with\nKeynote). Every format it leaves out gets one line on stderr, and the exit code stays 0:\n\n```\nskipped key: Keynote is macOS-only (this machine runs Linux). Fix: use -f pptx, which opens in PowerPoint, Keynote, LibreOffice Impress and Google Slides\n```\n\n**A format you name explicitly must be buildable**: `-f key` on Linux, or `-f pdf` without a\nbrowser, stops before anything is written, exit 1, one line with the reason and the fix.\n\n**Which browser prints the PDF**: `CHROME_PATH` if set (a wrong path is an error, not a\nfallback), else the first one found among installed Chrome, Chromium and Edge (Windows: the\nProgram Files and LocalAppData install folders; Linux: `google-chrome`, `chromium`,\n`microsoft-edge` on `PATH`, `/opt`, `/snap`; macOS: `/Applications` and `~/Applications`), else a\nbrowser downloaded by `npx playwright install chromium` or `npx @puppeteer/browsers install chrome`.\nNo browser at all: install Chrome or Edge, or run `npx playwright install chromium`.\n\nCI builds the examples with `-f all` on ubuntu, windows and macos runners on every push.\n\nSlides are separated by `---`. A comment picks one of the 12 Keynote White layouts;\nwithout it, whitedeck infers a sensible one.\n\n``` php\n---\ntitle: My Deck\nauthor: Me\n---\n\n<!-- _class: title -->\n# Big Title\n## Subtitle\n\n---\n\n<!-- _class: title-bullets -->\n# Agenda\n- First point\n- Second point\n  - Nested detail\n\n---\n\n<!-- _class: quote -->\n> \"Simplicity is the ultimate sophistication.\"\n> -- Leonardo da Vinci\n\n---\n\n<!-- _class: photo-horizontal -->\n# The ocean\n## A caption\n![](ocean.png)\n\nSource: [GSC Performance](https://search.google.com/search-console)\n\n---\n\n<!-- _class: compare -->\n# New template loads 3x faster than old\n- **Before**\n- LCP 4.1s\n- **After**\n- LCP 1.3s\n```\n\nLinks `[text](url)` render blue and underlined in every format (real hyperlinks in PPTX).\nA final `Source: [Name](url)` line becomes a small source note at the bottom of the slide.\nTitles that would overflow their box auto-shrink, exactly like Keynote.\n\nList all layouts: `whitedeck layouts`\n\n```\ntitle            title-center     title-top        title-bullets\nbullets          title-bullets-photo               photo\nphoto-horizontal photo-vertical   photo-3-up       quote            blank\ncompare          (virtual: side-by-side bullet columns on Keynote geometry)\ntitle-left       section-left     title-bullets-left   (left-aligned at a 54pt margin)\nscope-shot       scope-compare    scope-shot-notes     (annotated screenshot slides)\n```\n\nAnnotated screenshot slides carry a `Scope:` header line, a `Tool:` logo, bordered\nscreenshots (`![border=red label=\"JS on\"](shot.png)`), a notes column and a `Caption:` link;\n`logo: x.png` in the front matter paints a logo on every slide; `**bold**` and `[x]{#1db100}`\ncolour runs survive into PPTX and Keynote. See `examples/scope-demo.md` and the skill.\n\n```\nwhitedeck build deck.md -f html,pdf,pptx -o out/   # render formats\nwhitedeck build - -f pptx < deck.md                # stdin\nwhitedeck build deck.md -o out/board-q3.pptx       # exact file, format from the extension\nwhitedeck build deck.md -f all --name board-q3     # explicit base name\nwhitedeck layouts --json                           # machine-readable layout list\nwhitedeck validate deck.md                         # JSON report, exit 1 on errors\nwhitedeck init [name]                              # scaffold an example deck\n```\n\nOutputs are named after the **deck**, not after the input file: the front-matter `title`\n(or, without one, the first headline) becomes a slug.\n\n```\n---\ntitle: Q3 Revenue Review\n---\n```\n\n→ `q3-revenue-review.html`, `q3-revenue-review.pdf`, `q3-revenue-review.pptx`,\n`q3-revenue-review.key` - whatever the markdown file or the stdin pipe was called.\nUmlauts transliterate (`Über Größe` → `ueber-groesse`), slugs are capped at 60 characters\non a word boundary. Override with `--name <base>` or `-o <dir>/<file>.<format>`. A deck with\nno title and no input file name (stdin) is an error, not a file called `deck`.\n\n- **Claude skill** :`skills/whitedeck/SKILL.md` ships with the package - including the\neditorial persona (assertion headlines, max 5 bullets, one chart per slide, everything\nlinked to its data source).\n- **MCP server** :`whitedeck-mcp` (stdio) exposes`whitedeck_build` ,`whitedeck_layouts` ,`whitedeck_validate` .`whitedeck_build` follows the same format rules as the CLI and reports`built` and`skipped` (format, reason, fix):\n\n```\nclaude mcp add whitedeck -- whitedeck-mcp\n```\n\nTDD red-to-green, 100% integration tested, zero mocks - tests drive the real Marp, real Chrome, real Keynote.app and a real MCP stdio client:\n\n```\nnpm install\nnpm run gates    # typecheck, lint, test, build\nnpm run smoke    # build every example with -f all on this OS\n```\n\nMIT (c) 2026 Franz Enzenhofer\n\nNot affiliated with or endorsed by Apple Inc. Keynote is a trademark of Apple Inc. whitedeck contains no Apple assets - only independently measured layout geometry.", "url": "https://wpnews.pro/news/show-hn-whitedeck-black-on-white-keynote-like-slides-claude-skill", "canonical_source": "https://github.com/franzenzenhofer/whitedeck", "published_at": "2026-10-08 07:29:00+00:00", "updated_at": "2026-10-08 07:49:26.374333+00:00", "lang": "en", "topics": ["ai-tools", "ai-agents", "developer-tools", "generative-ai"], "entities": ["whitedeck", "franzenzenhofer", "Claude Code", "Apple Keynote", "Marp CLI", "PptxGenJS", "Node.js", "GitHub"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-whitedeck-black-on-white-keynote-like-slides-claude-skill", "markdown": "https://wpnews.pro/news/show-hn-whitedeck-black-on-white-keynote-like-slides-claude-skill.md", "text": "https://wpnews.pro/news/show-hn-whitedeck-black-on-white-keynote-like-slides-claude-skill.txt", "jsonld": "https://wpnews.pro/news/show-hn-whitedeck-black-on-white-keynote-like-slides-claude-skill.jsonld"}}