Install
$ agentstack add skill-hacka0wi-snapdeck-snapdeck ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
SnapDeck — live web app → polished PowerPoint
This skill produces decks the way a good design pipeline does: author each slide as HTML/CSS, render it to a 1920×1080-class PNG with headless Chrome, and drop the PNGs into the deck full-bleed. Do NOT lay slides out with python-pptx textboxes/shapes — pixel control (shadows, gradients, fonts, framed screenshots) is the whole point.
Two kinds of slide:
- Design slides (title, dividers, diagrams, tables, code) — HTML/CSS → PNG. Network-free.
- Screenshot slides — REAL captures of the running app, placed full-bleed with optional
numbered callouts. Captured via headless Chrome driving the live app (CDP).
Pipeline (3 stages)
1. CAPTURE scripts/capture.js live app → shots/.png + shots/.rects.json
2. GENERATE scripts/slides.py content + shots → slides/.html (design system)
RENDER scripts/render.js slides/*.html → slides/*.png (headless Chrome, dsf 2)
3. ASSEMBLE scripts/assemble.py ordered slides/*.png → out.pptx (16:9, full-bleed)
Work in a scratch dir (e.g. the session scratchpad), npm i puppeteer-core once, and use the system Chrome via executablePath (not a bundled Chromium). Run capture/render with the sandbox disabled (they need network + to launch Chrome).
Prerequisites
- System Google Chrome (
/Applications/Google Chrome.app/Contents/MacOS/Google Chromeon macOS). - Node:
npm i puppeteer-corein the work dir. - Python:
python3 -m pip install python-pptx Pillow. On macOS, a broken Homebrewpython3
(3.14 pyexpat) is common — use python3.11 if import pptx fails.
Capturing the live app (the hard, valuable part)
scripts/capture.js is config-driven. Key techniques baked in — keep them:
- Skip login by injecting the session. Most SPAs keep auth in
localStorage. Read the
value from a browser you're already logged into (e.g. via the Chrome MCP javascript_tool: localStorage.getItem('auth-storage')) and write it to auth.json. capture.js sets it with page.evaluateOnNewDocument BEFORE any page script runs, so every navigation is authed. (httpOnly auth cookies are not needed — the client AuthGuard reads localStorage.)
- Force LIGHT mode (decks must be light). The app theme often re-asserts on hydration, so
set it BOTH ways and AFTER load: localStorage[themeKey]=light, emulateMediaFeatures prefers-color-scheme:light, and document.documentElement.setAttribute('data-theme','light') right before each screenshot. Verify each shot is light before using it.
- Open modals/rows with a REAL mouse click at the element's bounding-box centre
(page.mouse.click(x,y)). el.click() frequently does NOT trigger row/card handlers.
- Open forms/tabs by button/tab text, preferring the smallest top-right-most match
(avoids clicking a wrapper div that merely contains the text).
- Read element rects (
getBoundingClientRectin CSS px at the capture viewport) for every
element you'll point a callout at — labels→their input, menu items, buttons, table rows. Store them in .rects.json so the generator can place crisp markers deterministically.
- Below-the-fold fields need a
scrollIntoViewthen a second capture/rects file. - Never trigger destructive actions to get a screenshot (delete, encrypt a real column,
submit a form against prod). Capture the screen that SHOWS the control; don't click it.
Capture viewport: 1600×1000 at deviceScaleFactor:2 (→ 3200×2000 PNG). This is 16:10; see the full-bleed crop note below.
Design system (lock every value; adapt per brand)
- Font: Prompt (via Google Fonts
@import; headless Chrome fetches it). Latin/technical
terms highlighted in accent blue (.hl); Thai heading then (English term).
- Colours: navy
#16264ftext, accent#2563eb, success#0f9950, old/red#d93a3a. - No score numbers, no
✓glyphs (reads as AI filler). Headings lead with the useful action. - Footer: small, neutral (set to the deck's product). Page numbers optional.
Screenshot-slide layout (what the user converged on)
- Full-bleed: the screenshot fills the entire slide. No white border, no frame.
- A compact frosted card top-left = pill + title ONLY (no step legend) so it never covers
form fields.
- Numbered circle markers placed BESIDE the target element (to its right; flip left if it
would run off-slide). No ring/box outlines — number only, never overlapping content.
- Full-bleed crop math: a 16:10 capture into a 16:9 slide with `object-fit:cover;
object-position:top shows the **top 90%** of the image. So marker% = x/1600, y/900 (use VYH=900`, not 1000). Elements you annotate must be within the top 900 logical px.
- "Result" screens with no steps → caption card (pill + title + one-line description), no markers.
Assembling
scripts/assemble.py builds a fresh 16:9 deck (13.333×7.5 in) and adds each PNG full-bleed (add_picture(png,0,0,width=W,height=H)) in an explicit ORDER list. When restyling an existing deck, first extract its embedded images + titles (python-pptx shape.image.blob, shape.text_frame) to reuse content, then regenerate every slide as a PNG and assemble fresh.
QA
Thumbnail-grid the result (pptx skill's scripts/thumbnail.py) and eyeball: every slide light mode, markers beside (not on) content, cards not covering key fields, consistent footer, correct order. Re-render only the slides you change.
Files
scripts/lib.js— puppeteer helpers (session inject, force-light, click-by-text, rect read).scripts/capture.js— config-driven live capture (edit theCFG/AUTH/ORIGINat top).scripts/slides.py— full-bleed HTML generator:steps_slide()(markers) +caption_slide().scripts/render.js— renderslides/*.html→ PNG at 1280×720 dsf 2.scripts/assemble.py— ordered PNGs →.pptx.example-config.json— a worked capture config.
These are templates: copy into your work dir and adapt the CONFIG blocks (origin, Chrome path, auth/theme keys, per-page targets, slide content, order) to the target app.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: hacka0wi
- Source: hacka0wi/SnapDeck
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.