skills/dvx-marp-presentation/SKILL.md
Create and iterate on MARP Markdown slide decks with HubSpot styling (two themes available — Trellis product palette and HubSpot brand-identity palette), AI-generated images via LiteLLM/Gemini, and slidegauge linting. Use when the user wants to create a presentation, build slides, make a slide deck, or work on a talk.
npx skillsauth add jeffvincent/claude-config marp-presentationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Build polished MARP slide decks with HubSpot styling and AI-generated illustrations.
This skill helps you create Markdown-based presentations using MARP. It includes:
assets/trellis-theme.md — HubSpot product-UI palette (dark navy + magenta + cyan, Trellis design tokens). Good for internal engineering / product-context decks.assets/hubspot-theme.md — HubSpot brand-identity palette (cream + orange + dark teal + maroon, Lexend Deca + Caveat). Good for executive, external, or brand-aligned decks.MARP converts Markdown to slides. It runs via npx (no global install needed):
# Test it works
npx @marp-team/marp-cli --version
If npx is not available, install Node.js first. Alternatively, install marp-cli globally:
npm install -g @marp-team/marp-cli
The image generation script uses uv to manage Python dependencies inline. Install uv if not present:
curl -LsSf https://astral.sh/uv/install.sh | sh
Install globally via uv:
uv tool install "slidegauge @ git+ssh://[email protected]/HubSpotEngineering/slidegauge"
slidegauge --help
slides.md:
assets/trellis-theme.md — product-UI palette (Trellis: dark navy + magenta + cyan). For internal engineering / product-context decks.assets/hubspot-theme.md — brand-identity palette (cream + orange + dark teal + maroon, Lexend Deca). For executive / external / brand-aligned decks.npx @marp-team/marp-cli --server <directory>lead / section-divider / agenda slide classes; the HubSpot brand theme adds a dark class)uv run scripts/generate-image.py -o images/my-image.png "a friendly robot"slidegauge slides.md<!-- ... --> HTML comments for talk trackUse MARP's <!-- _class: classname --> directive. Both themes support the shared classes; the HubSpot brand theme adds dark.
Shared (both themes):
lead — Title/intro slides, centered heading.section-divider — Section breaks. Magenta (Trellis) or maroon (HubSpot brand), white text.agenda — Agenda slide with styled ordered list.HubSpot brand theme only:
dark — High-contrast accent slide. Dark teal background, cream text, orange headings. Good for climax / turn moments.See each theme file for exact colors and per-class CSS.
 <!-- Left side, 35% width -->
 <!-- Right side, contained -->
For section divider slides, use bg left:35% so the image fills the left and text stays right.
Always include speaker notes with your talk track:
# Slide Title.
Visible text here.
<!--
This is the speaker note. Include your full talk track here — everything you plan to say.
Keep slide text minimal, put the detail in notes.
-->
For slides that need custom sizing (e.g., large code samples):
<style scoped>pre code { font-size: 0.43em; line-height: 1.1; }</style>
# My code slide.
Use scripts/generate-image.py to create illustrations via HubSpot's LiteLLM proxy (Gemini).
# Text-only prompt
uv run scripts/generate-image.py -o images/output.png "a friendly cartoon robot"
# With reference image(s) for style matching
uv run scripts/generate-image.py -o images/output.png -i reference.png "redraw this character waving"
# Specify aspect ratio (default 1:1)
uv run scripts/generate-image.py -o images/output.png -a 9:16 "tall portrait illustration"
uv run scripts/generate-image.py -o images/output.png -a 16:9 "wide landscape scene"
# Use the pro model for higher quality
uv run scripts/generate-image.py -o images/output.png --pro "detailed illustration"
9:16 aspect ratio for images that will be bg left:35% on section dividers16:9 for images that will be bg right:40% contain on content slides1:1 for character portraits or icons-i to maintain consistent art style across a deckhs-py-auth for authentication (auto-managed by uv inline deps)When creating diagrams for slides, follow this two-step process:
First draft the diagram as ASCII art in a markdown code block. This lets you iterate on structure and content quickly without waiting for image generation. Use box-drawing characters (┌─┐│└─┘├┤), arrows (→ ↓ ←), and clear labels.
Once the ASCII diagram is approved, convert it to a clean generated image using the image generation script:
uv run scripts/generate-image.py -a 16:9 -o images/<name>.png "Create a clean, professional infographic diagram on a white background with monospace font. [DESCRIBE THE DIAGRAM STRUCTURE]. Clean lines, minimal, dark text on white. Professional technical diagram style, not cartoon. Use subtle color coding: blue for user/input elements, gray for processing/thinking, orange for actions/tools, green for output/success, red for errors/failures. No decorations or illustrations."
-a 16:9 for full-width diagrams, -a 9:16 for sidebar images-i, add "matching the clean style, not the cartoon style"Replace the ASCII code block with:

Adjust w: value based on slide layout (900 for full-width, 500-550 for slides with sidebar images).
Run slidegauge to check slide quality:
slidegauge slides.md
Parse results for quick summary:
slidegauge slides.md 2>/dev/null | \
python3 -c "
import json, sys
data = json.load(sys.stdin)
s = data['summary']
print(f'Score: {s[\"avg_score\"]:.0f}/100 | {s[\"total_slides\"]} slides | {s[\"passing\"]}/{s[\"total_slides\"]} passing')
for sl in data['slides']:
if sl['score'] < 70:
print(f' FAIL: \"{sl[\"title\"]}\" ({sl[\"score\"]})')
for d in sl['diagnostics']:
print(f' {d[\"message\"]}')
"
Start the MARP preview server for live reload:
npx @marp-team/marp-cli --server <directory-containing-slides>
This serves at http://localhost:8080/ and auto-reloads on file changes.
Important: The server only serves static files — it does not auto-convert .md → .html on request. You must render HTML first (see Claude review loop below).
When you're iterating on styling and want Claude to verify a single slide visually, use this loop instead of re-rendering all PNGs on every change:
cd <deck-directory>
npx --yes --registry=https://registry.npmjs.org/ @marp-team/marp-cli@latest --server . & # dev server
node ~/.claude/skills/browser-automation/resources/browser-start.js --headless # headless Chrome
Edit the deck .md or theme asset.
Render HTML only (fast — ~2s, skips image/PDF):
npx --yes --registry=https://registry.npmjs.org/ @marp-team/marp-cli@latest deck-marp.md --html --allow-local-files -o deck-marp.html
Navigate (hard-load the page so new styles pick up):
node ~/.claude/skills/browser-automation/resources/browser-navigate.js "http://localhost:8080/deck-marp.html"
Advance to slide N by dispatching N-1 right-arrow keystrokes (hash-routing doesn't trigger bespoke's listeners after a page load):
node ~/.claude/skills/browser-automation/resources/browser-eval.js \
'for(let i=0;i<13;i++){document.body.dispatchEvent(new KeyboardEvent("keydown",{key:"ArrowRight",code:"ArrowRight",keyCode:39,which:39,bubbles:true}))} new Promise(r=>setTimeout(()=>r(document.querySelector("svg.bespoke-marp-active").querySelector("section").id), 400))'
(13 ArrowRight presses lands on slide 14 — adjust the loop count.)
Screenshot just the active slide element:
node ~/.claude/skills/browser-automation/resources/browser-screenshot.js \
--output=slide-N.png --element="svg.bespoke-marp-active"
Read the PNG in the Claude conversation and verify.
node ~/.claude/skills/browser-automation/resources/browser-close.js
# then kill the marp --server background job
#/N hashMarp bespoke's slide router attaches its hashchange listener after the initial goto. Setting location.hash = "#/14" after page load fires a hashchange but bespoke's handler often doesn't wire up in time. Dispatching ArrowRight keydown events on document.body is the most reliable way to drive bespoke's internal state.
Rendering all 23 slides to PNG takes 30+ seconds. Rendering the same deck to a single .html file takes ~2s. The browser-driven screenshot gives you a single-slide visual in the same time you'd otherwise wait for one re-render.
See assets/trellis-theme.md for the full theme. Key colors:
| Token | Hex | Usage |
|---|---|---|
| Slate | #33475B | Default slide background |
| Dark Slate | #1a2633 | Code block / table header |
| HubSpot Orange | #FF5C35 | Headings, accent |
| Trellis Magenta | #A83D5C | Section dividers, CTA slides |
| Light Pink | #FDEDF2 | Lead/title slides |
| Cyan | #00A4BD | Emphasis text, links |
| Off White | #f5f8fa | Body text |
See assets/hubspot-theme.md for the full theme. Key colors:
| Token | Hex | Usage |
|---|---|---|
| Cream | #F5F0EB | Default background, lead slides |
| Dark Text | #2D3748 | Default body text |
| Panel BG | #ECE7E1 | Card surface |
| HubSpot Orange | #FF5C35 | Headings, numbers, bullets, accent bars |
| Maroon | #3D1126 | Section dividers, "Then" heading in compare |
| Dark Teal | #042729 | .metric card, .dark accent slides |
| Divider | #DDD8D2 | Hairline dividers |
Fonts: Lexend Deca (300 Light for headings, 400 for body), Caveat (hand-drawn accents).
tools
Render a video clip with captions overlaid, using the Remotion captioner at `/Users/jvincent/Projects/remotion-captioner/`. Use when user provides a video file and wants to add captions/subtitles, mentions "caption this video", "add captions", "burn in subtitles", or provides a video + SRT file pair.
development
Upload video files to Wistia projects using the Data API. Use when user wants to upload videos to their Wistia account for hosting, transcription, or sharing.
development
Transcribe voice memos to text using Whisper. Use when user provides audio/video files (.m4a, .mp3, .mov, etc.) and asks to transcribe them into text and SRT format with timestamps.
testing
# Voice Authenticity Reviewer ## Purpose Review any written content for alignment with authentic speaking and writing voice using analyzed patterns from 7 meeting transcripts and strategic memos. ## When to Use This Skill - Before sharing strategic memos with leadership - Before sending important emails - When drafting presentation scripts - When reviewing documentation for external sharing - As part of Writing /produce-memo workflow (Step 6) - Anytime voice authenticity verification is needed