How it is built, how it works, and how anyone who receives a deck can edit it.
Three sections. Each stands on its own.
A design system inspired by the NBG brand, a build pipeline and an in-deck editor, packaged as one Claude skill.
One Claude Code skill that turns a request into a finished presentation in a look inspired by the NBG brand.
Four problems every presentation team knows, and how the skill answers each.
Every deck shares one look. One palette, one type stack, one artboard, one logo lockup — enforced by the skill, not by the author's memory.
The verifier rejects a deck with a fake logo, a missing photo or an external image path.
From any content to a finished deck in minutes — a brief in chat, notes, a document, a spreadsheet, an existing deck or a Google Slides draft. Once the generator exists, every re-run is one command.
One self-contained file. It can be emailed, put on a share or opened from a USB stick; it renders identically everywhere because nothing points back to the machine that built it.
Recipients fix their own slides. A typo, a longer title, a card that should be teal, a row that needs aligning — done in place, saved as a copy, exported to PDF — without a regeneration.
The skill moves the effort from making slides look right to deciding what they should say.
The files of a deck, produced and verified the same way every time.
deck.rebuild.mjs: run it after the skill is updated and the deck receives the newer editing tools, verified, with its PDF re-exported — no regeneration.No fallbacks: a missing input is a question to you, never a silent default.
What arrived most recently in the skill. Each is explained further on; the recipient needs no new tooling for any of them.
<deck>.rebuild.mjs: after a skill update it re-embeds the newer editing tools, keeps a backup, re-verifies and re-exports the PDF.--check only reports.27 bundled photos with a written catalogue (Athens at dusk, data centre, network, microchip, security, developer, team analytics — three takes each); assistant settings kept per provider and an Ask about… popup on any row of the Outline or Tree; a full set of keyboard shortcuts for text, shapes, SVG parts and panels; PDFs whose shadows render correctly in macOS Preview (1.19); four themes chosen per deck — NBG, BikS2013, AIHub, Instrument (1.20–1.23).
Asking for a deck, what happens in between, the quality gates, and everything the right-click editor can do.
One public marketplace, two commands. No npm install, no build step: the skill is Markdown, assets and zero-dependency Node scripts.
github.com/BikS2013-coding-agents/nbg-design (branch working); its name and the plugin's name are both nbg-design, hence nbg-design@nbg-design.~/.claude/plugins/cache/nbg-design/nbg-design/<version>/; the skill root is its skills/nbg-design/ folder — the <skill-root> the pipeline commands use.node <deck>.rebuild.mjs re-embeds the newer editing tools — pointed at the new cache folder with --scripts or NBG_DESIGN_SCRIPTS when the recorded one is gone.What the skill needs from you, what it decides by itself, and what it refuses to do.
gr and bi exist; anything else must come from you.A brief typed in chat, meeting notes, a Word or Markdown document, a spreadsheet, a report, an existing HTML deck, or a Google Slides draft (read through the Slides API and rebuilt 1:1, page count kept). The skill turns whatever it is given into a cover, dividers and content slides; it only asks for what it cannot infer.
One request, three answers, one command chain, two files — and a recipient who can edit the result.
Claude authors; the scripts embed, add the editor and verify; a failing gate sends the deck back to the author, never forward.
What each step does and the command behind it. Steps 2 to 4 and the rebuild script are mandatory for every deck.
Claude writes the deck on the 1920×1080 artboard, the design-system CSS and placeholders where images go: {{LOGO_PRIMARY}}, {{PHOTO_STREET}}.
Every token becomes the verbatim base64 image. The script finds the assets next to itself, so it works from any folder and any machine.
embed-assets.mjs deck.htmlOne script block is inlined before </body>: the right-click menu, editing, toolbars, assistant, print. Re-running upgrades an older block.
Browser-free gate: no unresolved tokens, no external image paths, real logo, enough images, current menu. A failing deck is never delivered.
verify-deck.mjs deck.html --strictThe rebuild script is written next to the deck; screenshots are read for overlaps and clipping; the PDF is printed, and on request the PowerPoint file converted and compared.
screenshot-deck · export-pdf · export-pptxHand-pasting a 600 KB base64 photo is the step that silently fails on a headless run. Tokens make embedding a script's job, and the gate catches any slip.
Inspired by the NBG brand and distilled into one HTML reference: nine colours, one typeface and nine templates.
16:9, 1920×1080 artboard, scaled to fit any viewport. Aptos for everything, with a system fallback where it is absent — the stack is never swapped.
Covers (hero photo, image card, alternate), dividers (photo, deep teal, bright), content (image right, two columns, stat-led). Content pages stay calm and mostly monochrome; accent blocks belong to covers and openers.
Three logo lockups — primary for light backgrounds, knockout for dark, small for footers — and five photographs, each shipped with a ready-made data URI. The logo is always the image, never text or a box.
What must be true before a deck leaves. The first gate runs anywhere; the others need a browser.
file://, absolute, relative or http path — every image is a data: URI.“NBG” text nodes that could stand in for the lockup fail the gate.Five families of actions, all in the file itself, all recorded and reversible. The slides that follow walk through them, and end with every keyboard shortcut.
Every delivered deck carries its own editor. Right-click anywhere on a slide; Escape or a click outside closes it.
Double-click any text. The whole block becomes editable in place, with a teal outline; the slide's CSS is never touched.
Right-click a card, photo panel, image or text block → Resize / move shape. A teal frame with eight handles appears.
Right-click a drawn icon, diagram or chart → Edit SVG. The drawing gets a dashed outline and every part inside it becomes a thing you can pick.
use reference or group. Nothing inside defs, clip paths, masks or symbols.Geometry goes into attributes, colour into presentation attributes, and the whole drawing becomes one reversible record. The path data itself is never touched.
x / y / width / height; a pure move of text, a use, a circle, an ellipse or a line changes x / y, cx / cy or x1…y2.matrix() prepended to its own transform. The d attribute stays as drawn.<text>; labels with several runs are edited as source in the Tree tab.<svg> element's inner HTML as a single html edit — the same kind as a text edit — so it persists in the browser, lands in the saved copy, is discarded per slide and prints.contenteditable; the SVG as a whole is still a shape for Resize / move shape.The frame is the axis-aligned screen box: a part inside a rotated group is moved correctly in that group's space, but its frame does not rotate. Parts sized in percentages or with a CSS transform take the matrix path. The five diagrams in this deck are editable this way.
Text blocks, cards, panels and images alike. The frame spans the selection and each member gets a dashed mark.
data-nbg-group mark and always select, move, resize, align and order together.A click lands on one level only. Use Select at this point in the menu (front-most first, containers, shapes behind), the toolbar's Stack list, or Tab / Shift+Tab to reach the others.
The Outline and Tree tabs, panels that leave the browser window, and the compact menu that takes over while the big one is away.
Text, Shape and SVG share one floating panel with one grip, one anchor and one detach button. One tab's row shows at a time.
Three real screenshots from this deck: the Settings view, the Ask view with a card selected, and the Ask-about popup opened from a row of the Outline.
An AI request from inside the deck, with the slide as context. The viewer brings their own endpoint and key; nothing is baked in.
Each attachment is a checkbox, so the viewer decides per request what leaves the machine. The key never enters the deck file or a saved copy.
The deck on disk never changes by itself. Edits live in the browser until you save a copy.
<name>-edited.html: your edits applied to a pristine snapshot of the deck taken at load. The copy is still one self-contained file and carries the editor itself.node deck.rebuild.mjs replaces only the editor block with the one the skill ships now, keeps a backup, re-runs the strict gate and re-exports the PDF. --check only reports CURRENT or REBUILD NEEDED.| In the deck, by anyone | By regenerating, with the skill |
|---|---|
| Text, formatting, size, font, palette colour, alignment | New images or photos |
| Geometry and style of shapes: fill, border, radius, opacity, shadow | New elements, new slides, new layouts |
| Order, alignment, distribution, groups of several shapes | Structural changes to the page |
| AI-assisted rewrites and restyles of an element | Anything outside the skill's fonts and palette |
A PDF of an edited deck is printed from the saved copy — the CLI prints what is on disk.
Every shortcut the editor understands, by mode. Ctrl on Windows and Linux, Cmd on a Mac; deck navigation keys are paused while you edit.
| Enter | applies the edit; a click outside does the same |
| Esc | cancels the edit and its formatting |
| Shift+Enter | line break |
| Ctrl/Cmd+Z | undo while editing |
| Ctrl/Cmd+B I U | bold, italic, underline |
| Ctrl/Cmd+Shift+> < | larger / smaller text |
| Double-click | a text: start editing it |
| ↑↓←→ | nudge by 1 px; Shift 10 px |
| Alt+arrows | resize |
| Tab Shift+Tab | enclosing shape / child shape |
| Shift+click | add the smallest shape there, or remove a selected one |
| Shift+drag | selection box on the slide |
| Ctrl/Cmd+click | everything inside the shape; a leaf alone, again cycles outward |
| Ctrl/Cmd+A | every top-level shape of the slide |
| Ctrl/Cmd+] [ | forward / backward; Shift front / back |
| Ctrl/Cmd+G Shift+G | group / ungroup |
| Esc Enter | finish |
| Click | innermost part; drag moves it |
| Shift+click | add a part, or remove a selected one |
| Ctrl/Cmd+click | what is inside the part there |
| Ctrl/Cmd+A | every top-level part |
| Tab Shift+Tab | enclosing group / first part inside |
| ↑↓←→ | nudge one unit; Shift ten; Alt resizes |
| Ctrl/Cmd+] [ | drawing order; Shift front / back |
| Ctrl/Cmd+D | duplicate |
| Delete Backspace | delete the part |
| Esc | deselect, then end; Enter ends |
| Right-click | the menu, or the picker while the menu is away |
| Esc | closes the menu, the picker, a popup |
| Ctrl/Cmd+Shift+O | Outline tab |
| Ctrl/Cmd+Shift+H | Tree tab with the element's source |
| Ctrl/Cmd+Shift+L | the assistant |
| Ctrl/Cmd+V | paste an image into the assistant's request |
| Double-click | a shape selects it; a selected drawing opens its parts; a grip releases an anchored panel |
How it is built: the folder, the scripts and libraries, the editor's internals, the PDF and PowerPoint paths, the configuration hook and the rules to keep.
Each layer rests on the one below; extend the one you need. The editor is the layer that turns a deck into something recipients can change themselves.
31 MB, 30 of them photography; one Markdown file that is the whole behaviour, nine scripts, seven libraries, and four themes with their assets.
.claude/skills/ pointing at the plugin checkout, so the working tree is the live skill.Zero-dependency Node (18+). No npm install, no build step; nine single-file scripts that import from lib/.
| Script | What it does | Needs | Exit codes |
|---|---|---|---|
| embed-assets.mjs | Replaces every {{TOKEN}} with the verbatim data URI; tokens map to files by name; fails loudly on a missing asset. | none | 0 / 1 |
| add-deck-menu.mjs | Inlines one <script id="nbg-deck-menu-script" data-nbg-deck-menu="17"> before the last </body>: print-layout.js then deck-menu.js. Idempotent; upgrades older blocks; --remove strips. | none | 0 / 1 |
| verify-deck.mjs | The gate: tokens, image paths, image count, size, bare-logo text, editor block version. --strict promotes the warnings to failures. | none | 0 pass / 1 fail |
| write-rebuild-script.mjs | Writes <deck>.rebuild.mjs next to the deck: a self-contained script that later re-embeds the skill's current editor block (backup, verify, re-export the PDF); --check only reports. | none | 0 / 1 / 2 |
| screenshot-deck.mjs | Drives a headless browser over the DevTools protocol; isolates the Nth .slide in place, so .active, .hidden, inline-display and stacked decks all work; PNG per slide per viewport. | browser | 0 / 1 / 3 no browser |
| export-pdf.mjs | Lifts the host layer, prints with Page.printToPDF at the slide box, verifies pages = slides and slide box = page box; then re-anchors the soft masks so shadows render in macOS Preview. | browser | 0 / 1 / 3 no browser |
| fix-pdf-soft-masks.mjs | Re-anchors the soft masks of a PDF exported earlier (or saved from the print dialog): an incremental update, the original bytes intact; --check only reports. | none | 0 / 1 / 2 |
| export-pptx.mjs | Measures every slide in the browser and writes an editable .pptx: text boxes with real runs, shapes, cropped pictures, SVG pictures, the theme's fonts and colours. | browser | 0 / 1 / 3 no browser |
| compare-pptx.mjs | Renders the .pptx with PowerPoint (macOS) or LibreOffice and writes deck | PowerPoint | difference images with a score per slide. | browser | 0 / 1 / 3 missing tool |
Locates Chrome, Chromium or Edge; --browser, NBG_BROWSER, CHROME_BIN override.
A minimal DevTools-protocol client over the debugging pipe: launch, navigate, evaluate, print, count pages.
The print shim shared by the exporter and the in-deck menu; a registry undoes every change after printing. On the menu path it prints blurred shadows as images (v13).
Zero-dependency PDF rewriter: re-anchors Chrome's luminosity soft masks so macOS Preview renders shadows; incremental update.
The editor: ~4,000 lines of plain browser JavaScript — editing, selection, SVG parts, toolbars, structure, assistant, persistence, print.
pptx-extract.js measures every slide in the browser; pptx-writer.mjs writes the Office Open XML and its zip.
One HTML file carries the slides and the editor; the browser keeps the edits; three ways lead out.
How a standalone file:// deck can be edited, remembered and handed back without ever writing to itself.
{{ path, original, … }} where path is the child-index path from the root — cheap, exact, and the reason the DOM is never restructured.data-nbg-group attribute). An SVG session records the whole <svg> as one html record.localStorage under nbg-deck-edits:<path>#<title>; re-applied on load; a record whose original no longer matches is dropped.outerHTML snapshot.DOMParser, applies the records, and downloads the result: it loads exactly like the original and carries the menu.rect.width / offsetWidth), so coordinates are artboard pixels.z-index; a negative index makes the parent a stacking context with isolation: isolate.contenteditable, not plaintext-only, because the latter forces pre-wrap and re-flows titles.Inline style and attributes only, never DOM re-ordering — so every earlier record's path stays valid and every change stays reversible.
The PDF is the deck, printed by the same engine that renders it. Nothing is re-laid out for paper.
.active, .hidden, inline display), the viewport-fit wrappers and scaling, buttons and counters; jumps animations to their end state; forces print-color-adjust: exact..slide visible in flow and prints with Page.printToPDF: page size = the measured slide box (1920×1080 px = 20 × 11.25 in), zero margins, backgrounds on, scale 1.fix-pdf-soft-masks.mjs does it for older PDFs.window.print() at A4, no browser Save-as-PDF with headers and margins, no office round-trips, no stitched screenshots.slide class — the exporter and the screenshot helper key on it.verify-deck --strict. The in-deck Export to PDF inlines the very same shim; since the print dialog's PDF cannot be post-processed, that path prints blurred shadows as images instead (block v13).An editable .pptx, converted element by element from the deck the browser lays out. Never a screenshot per slide.
Two slides of this very deck: the HTML, its .pptx as rendered, and the pixels that differ. compare-pptx writes one such image per slide.
Left the deck, middle the .pptx (here rendered by LibreOffice), right the differences in red. Below about 0.5 % solid difference is anti-aliasing and sub-pixel font metrics; text that re-wraps or a shape out of place would show as a red block.
Since v1.15 the editor is configured, not forked. A deck keeps its defaults; any other document declares what its editable regions are.
addMenu(html, config) / buildMenuBlock(config); readMenuConfig(html) reads it back. The CLI has no flags: a deck always gets the defaults.add() per slide, sharing one deck.css and deck.js with sibling decks.rebuild.sh per deck detects skill, generator or asset changes, builds the next version through the five steps and refreshes a fixed-name -latest copy — the stable link.The constraints written into SKILL.md that every generated deck, and every future change to the skill, must respect.
data: URI; the logo always the bundled lockup.One line for recipients, eight commands for builders, one marketplace to install from.
Double-click any text to edit it (Enter applies, Esc cancels). Right-click for Resize / move shape (Shift+click or Shift+drag selects several; the toolbar orders, aligns, distributes and groups them), Edit SVG (the parts of a drawn icon, diagram or chart; one toolbar with Text, Shape and SVG tabs serves all three), Ask the assistant, Export to PDF and Save edited copy. After a skill update, node deck.rebuild.mjs refreshes the editing tools and the PDF.
github.com/BikS2013-coding-agents/nbg-design: /plugin marketplace add BikS2013-coding-agents/nbg-design, then /plugin install nbg-design@nbg-design.github.com/BikS2013-presentations/deck-work-nbgdesign, browsable on GitHub Pages and always current as deck/NBG-Design-Skill-Explained-latest.html; its generator and rebuild.sh live in the same repository.