plugins/octave/skills/deck/SKILL.md
Octave-powered presentation builder that researches, structures, and generates self-contained HTML slide decks. Use when user says "build a deck", "create a presentation", "pitch deck", "QBR slides", "sales deck", or asks for slides on any topic.
npx skillsauth add octavehq/lfgtm deckInstall 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 compelling, self-contained HTML presentations powered by your Octave GTM knowledge base. Unlike generic slide builders, this skill leverages your library's personas, competitors, Motion ICP narratives, proof points, and real conversation data to research, structure, and generate presentations grounded in your actual go-to-market intelligence.
HTML presentation engine inspired by frontend-slides by Zara Zhang (MIT license). Decks render on a fixed 1920×1080 stage scaled to the viewport (see references/viewport-base.css).
A deck is customer-facing, so whose brand it wears is a real choice — offer the recipient's (the target company's) brand for a personalized, made-for-you feel; the sender's brand is the standard alternative. Follow the kit lookup, defaults, and extraction tiers in ../shared/brand-kit-usage.md.
Run the default review pass after generating — the always-on preflight plus the visual render-and-inspect pass, per ../shared/review-pass.md. Opt out with --skip-review. When generating, follow the output rules in ../shared/presentation-principles.md.
/octave:deck [topic or file] [--for <purpose>] [--audience <target>] [--style <preset>] [--skip-review]
/octave:deck "pitch for Acme Corp" # Customer pitch, Octave researches Acme
/octave:deck "Q1 QBR for enterprise segment" # QBR with real pipeline data
/octave:deck --for competitive "vs Gong" # Competitive presentation
/octave:deck "product launch GTM plan" # Internal strategy deck
/octave:deck ~/Downloads/existing-deck.pptx # Convert PPTX to HTML
/octave:deck "demo day pitch" --style octave-brand # Specific style preset
/octave:deck "sales kickoff enablement" --audience "new AEs" # Audience-targeted
When the user runs /octave:deck:
Establish five things before researching — purpose (customer pitch / QBR / internal strategy / keynote / launch / competitive / enablement), goal (the outcome the deck should drive), audience (company, person, role, or general group), content readiness (from scratch, notes, pasted content, or a PPTX file), and length + density (slide count and speaker-led vs reading-first).
Anything not provided via flags or the prompt, ask interactively using the question menus and per-purpose defaults in references/intake.md. If a .pptx file is provided, jump to the PPTX Conversion Path before continuing.
Carry the density choice through Step 5: it drives the content limits per slide type (split into more slides rather than shrink text or overflow).
Based on purpose, goal, and audience, use Octave MCP tools to build rich context for the deck. Always tell the user what you're researching and why.
Call as many tools as needed to build a complete picture. The best decks come from layering multiple sources — company enrichment + Motion ICP narrative + proof points + conversation intel all combine to create slides grounded in real data. Don't stop at one tool when three would give you a stronger narrative.
That said, not every tool applies to every deck. Use your judgment about which are relevant to this specific situation, and pick the combination that gives you the richest context for the deck type and audience:
Output of this step: Present a structured content brief to the user:
DECK OUTLINE: [Title]
=====================
Purpose: [Purpose from Step 1]
Audience: [Target audience]
Goal: [Desired outcome]
Length: [Short/Medium/Long/Custom] — [N] slides
Source: [From scratch / User content / PPTX conversion]
---
NARRATIVE ARC
-------------
1. HOOK — [Opening that captures attention]
2. PROBLEM — [Pain point or challenge]
3. SOLUTION — [How you solve it]
4. PROOF — [Evidence and social proof]
5. ASK — [Clear next step / CTA]
---
SLIDE-BY-SLIDE OUTLINE
-----------------------
Slide 1: [Title Slide]
• [Headline]
• [Subtitle/context]
Slide 2: [Problem/Challenge]
• [Key point 1]
• [Key point 2]
• [Data point from Octave]
Slide 3: [Solution Overview]
• [Value prop 1]
• [Value prop 2]
• [Value prop 3]
[Continue for all slides...]
---
Octave Sources Used:
• Company profile: [Company name] — [key insights]
• Motion / Motion ICP: [Motion name + persona × segment cell] — [key messaging angle]
• Proof points: [N] references pulled
• Competitive intel: [If applicable]
• Findings: [N] recent signals
---
Does this outline look good? I can:
1. Proceed to style selection and generation
2. Add/remove/reorder slides
3. Go deeper on any section
4. Change the narrative angle
Wait for user approval before proceeding.
Ask the user:
Whose brand should this deck reflect — and how should we style it?
1. My brand (the sender) — extract from my website (give the URL)
2. The audience's brand — mirror the recipient's company so the deck feels built for them (give *their* URL). Common for customer pitches and ABM.
3. I'll provide brand assets directly (colors, fonts, logo)
4. No brand — pick from style presets
5. Use Octave brand styling
Whose brand decides which website you fetch. For option 1 run the extraction against your own domain; for option 2 run it against the audience's/recipient's domain.
Check for a cached brand kit first, and if extraction is needed work down the tiers (Octave brand-assets tool → scrape_website → browser-use → WebFetch → manual), then confirm the extracted brand config with the user — all per ../shared/brand-kit-usage.md.
Ask the user how they want to choose their style:
How would you like to choose your style?
1. Show me options — I'll generate preview slides based on your mood
2. I know what I want — pick from 12 presets
3. Use my brand — auto-generate from brand extraction
4. Surprise me — I'll pick based on your deck purpose
Your choice:
Ask:
What impression should the deck make?
1. Impressed — premium, polished, high-stakes
2. Excited — energetic, bold, forward-looking
3. Calm — clean, trustworthy, understated
4. Inspired — creative, visionary, memorable
Your mood:
Generate 3 single-slide HTML preview files — show, don't tell. Each is a real, animated title slide using the user's actual first-slide content (title, subtitle, date, author, logo if available). Never render "Option A", "preview", a preset/template name, or any file path on the slide itself. Save to .octave-decks/slide-previews/ as style-a.html, style-b.html, style-c.html, built on the fixed 1920×1080 stage (paste viewport-base.css).
Preview mix: generate previews from the mood-matched presets in ../shared/style-presets.md, optionally swapping one for a custom wildcard:
| Mood | Preview presets |
|------|----------------|
| Impressed | midnight-pro, executive-dark, octave-brand |
| Excited | electric-studio, neon-pulse, solar-flare |
| Calm | swiss-modern, soft-light, paper-minimal |
| Inspired | dark-botanical, aurora-gradient, monochrome-bold |
For more range, make one of the three a custom wildcard — a self-generated design that follows the no-slop rules (distinctive typography, avoid Inter/Roboto/system fonts; a committed palette, no generic purple-on-white; a recognizable layout system on the fixed 16:9 stage). If brand was extracted in Step 3, add a 4th brand-themed preview.
Open all previews in the browser for the user to compare, then ask which they prefer (or which elements to mix).
Show the 12-preset menu (6 dark, 3 light, 3 vibrant) with one-line descriptions. Full CSS variable definitions for each preset are in ../shared/style-presets.md.
Auto-generate CSS variables from the brand config extracted in Step 3 (see ../shared/brand-kit-usage.md → "Applying an extracted brand"). Show the generated style to the user for confirmation.
Map deck purpose to recommended presets:
| Purpose | Recommended Preset |
|---------|--------------------|
| Customer pitch | midnight-pro |
| Customer QBR | executive-dark |
| Internal strategy | octave-brand |
| Conference keynote | electric-studio |
| Product launch | aurora-gradient |
| Competitive battlecard | neon-pulse |
| Sales enablement | soft-light |
Tell the user what you picked and why. Let them override.
Build a single, self-contained HTML file. No external dependencies. Everything inlined.
Every deck gets its own folder under .octave-decks/:
.octave-decks/
├── slide-previews/ # temp style previews (cleaned up after selection)
└── <kebab-case-name>-<YYYY-MM-DD>/ # one folder per deck
├── <name>.html # final HTML presentation
├── <name>.pptx # PPTX export (if requested)
├── <name>-carousel.html # LinkedIn carousel version (if requested)
├── <name>-content.md # markdown export (if requested)
└── assets/ # images (from PPTX conversion or user-provided)
Example: /octave:deck "pitch for Acme Corp" → .octave-decks/acme-corp-pitch-2026-02-07/acme-corp-pitch.html
Make sure .octave-decks/ is ignored by your project's .gitignore (an .octave-*/ pattern covers all Octave output dirs) so generated decks don't get committed.
See html-scaffold.md for the full scaffold. Two non-negotiables:
<style> block. It provides the .deck-viewport → .deck-stage (1920×1080) → .slide system, .active/.visible visibility, print-one-slide-per-page, and reduced-motion.clamp(), vw, or vh for layout. The stage scales as a whole to fit any screen.Every slide is a fixed 1920×1080 canvas; the controller scales the whole stage. Fit is achieved by density discipline, not responsive math:
clamp()/vw from a preset or custom design into fixed px.overflow: hidden on every .slide (from viewport-base.css) — anything that doesn't fit is clipped, so it must fit by design.| Slide Type | Max Content | |-----------|------------| | Title | 1 heading + 1 subtitle (2-3 lines max) | | Section Divider | 1 big heading + 1 subtitle. Chapter break. | | Content | 1 heading + 4-6 bullet points | | Grid/Cards | 1 heading + 6 cards maximum | | Quote | 1 quote (3 lines max) + attribution | | Metric | 1 heading + 3-4 big numbers | | Comparison | 1 heading + 2-column layout (6 rows max) | | Timeline/Process | 1 heading + 4-6 steps (label + short description each) | | Logo Wall | 1 heading + 8-12 logos in a grid | | Image | 1 heading + 1 image + 1 caption | | Agenda/TOC | 1 heading + 5-8 agenda items | | CTA/Closing | 1 heading + 1-2 lines + 1 action |
Reveals are triggered by the .visible class the controller toggles on the active slide (no Intersection Observer — slides switch via .active/.visible, not scroll):
.animate-in {
opacity: 0;
transform: translateY(30px);
transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}
.slide.visible .animate-in { opacity: 1; transform: translateY(0); }
/* Stagger children */
.slide.visible .animate-in:nth-child(1) { transition-delay: 0.1s; }
.slide.visible .animate-in:nth-child(2) { transition-delay: 0.2s; }
.slide.visible .animate-in:nth-child(3) { transition-delay: 0.3s; }
/* ... up to 8 */
Match motion to the chosen style (see references/animation-patterns.md for the effect-to-feeling guide and snippets: fade/slide, scale-in, blur-in, gradient-mesh backgrounds, 3D tilt). Use extras sparingly: counter animations for metrics, draw-in for borders, fade-scale for cards. prefers-reduced-motion is already handled by viewport-base.css.
A small SlidePresentation controller (in the scaffold) handles everything — no scroll-snap, no nav dots:
// 1. Stage scaling: transform = translate(x,y) scale(min(vw/1920, vh/1080)); re-fit on resize
// 2. show(i): toggle .active + .visible on the target slide (re-runs .animate-in reveals)
// 3. Keyboard: ArrowRight/PageDown/Space = next; ArrowLeft/PageUp = prev; Home/End; R = reset
// 4. Touch: swipe left/right
// 5. #deckControls (outside the stage, so it isn't scaled): "n / total" + prev/next buttons
Whether using a preset or a custom wildcard, the output should look intentional, not generated:
Copy is held to the same bar as visuals. Every word a viewer reads (headline, body, caption, pill, metric label) must pass the slop standard in ../shared/asset-review.md → WRITE_LIKE_A_HUMAN. Two rules break most decks, so treat them as hard rules, not preferences, and fix them in the review pass rather than excusing them as "headline style":
— and the literal —. Use a comma, colon, period, or two sentences. Hyphenated compounds (go-to-market) and arrows (6mo → 3wk) are fine.Add a lightweight in-browser editor so the user can tweak copy without touching code. Do not ask about it during intake — include it unless the user requested a locked/export-only deck. Implementation details (the JS-based hover with a 400ms grace period — not a CSS ~ sibling selector, which breaks because pointer-events:none drops the hover chain — plus the E shortcut and stripping edit state on export) are in html-scaffold.md.
Consult references/slide-templates.md for HTML templates for each slide type: title, content, grid/card, metric, quote, comparison, section divider, timeline, logo wall, image, agenda, and CTA. Mix types for visual variety.
After generating the HTML file:
.octave-decks/slide-previews/PRESENTATION READY
==================
Folder: .octave-decks/<deck-name>-<date>/
File: .octave-decks/<deck-name>-<date>/<deck-name>.html
Slides: [N] slides
Style: [Preset name or "Custom Brand"]
Size: [file size]
Navigation:
• Arrow keys / Space / Page Up-Down to move; Home/End to jump; R to reset
• Swipe left/right on touch devices
• Prev/next + "n / total" controls at the bottom
• Scales to fit any screen (fixed 16:9 stage, letterboxed)
Editing:
• Hover the top-left corner (or press E) to toggle inline edit mode, then
click any text to edit. Export saves a clean copy with edit state stripped.
Customization tips:
• Colors/fonts: edit the :root CSS variables at the top of the file
• Content: each <section class="slide"> inside .deck-stage is one slide
• Add slides: copy a <section class="slide"> block (only the first carries
"active visible")
---
Want me to:
1. Adjust specific slides
2. Change the style/colors
3. Add or remove slides
4. Create a version for a different audience
5. Export or share (PDF, live URL/Vercel, LinkedIn Carousel, PPTX, Google Slides, Gamma)
6. Done
Consult references/export-guide.md for detailed instructions per format:
bash "${CLAUDE_PLUGIN_ROOT:-.}"/scripts/export-pdf.sh <deck>.html (headless Playwright, one slide/page; --compact for smaller files). Browser print is the fallback.bash "${CLAUDE_PLUGIN_ROOT:-.}"/scripts/deploy.sh <deck-folder>/ deploys to Vercel and returns a public link that works on any device.
export-pdf.shanddeploy.share generic — the same commands work for any HTML output from the other Octave skills (one-pager, proposal, microsite, brief, wins-losses reports).
When a .pptx file is provided:
Use the bundled extractor (requires pip install python-pptx):
python3 "${CLAUDE_PLUGIN_ROOT:-.}"/scripts/extract-pptx.py <input.pptx> .octave-decks/<deck-name>-<date>
It emits a JSON structure of every slide (title, text paragraphs with levels, speaker notes) and saves embedded images to assets/ inside the output directory.
Note: Images from the PPTX are saved as separate files referenced by the HTML. The output is still a single HTML file, but images are external assets. Mention this to the user.
Common research, library, signals, and generation tools: see ../shared/octave-research-toolkit.md. Deck-specific additions:
get_external_brand_assets — Scrape a URL for brand colors, logo variants, backdrop images, brand name (Tier 1 brand extraction)get_external_brand_logo — Single best logo URL for a domainscrape_website — Fetch a page as markdown/html with an optional screenshot ({ format, includeScreenshot }) — used to read components/typography for brand emulation (Tier 2)list_entities (entityType: "brand_voice") — Available brand voices in workspacelist_writing_styles — Available writing styles in workspaceStandard responses (connection failed, company/person not found, no matching Motion ICP cell): see ../shared/octave-research-toolkit.md → Standard error handling. Deck-specific:
PPTX Extraction Failed:
Could not parse the PPTX file.
Options:
- Try a different file
- Export as PDF and I'll work from that
- Copy-paste the content manually
- Describe what the deck covers and I'll rebuild from scratch
Browser-Use Unavailable (Brand Extraction):
Browser automation isn't available for brand extraction.
Falling back to web fetch. If that doesn't capture your brand accurately, you can provide colors and fonts manually.
Style Preview Won't Open:
Could not open preview files in browser.
Preview files are saved at: [file paths]
Open them manually, or just pick a preset by name/number.
/octave:research - Deep account research (feeds into deck content)/octave:battlecard - Competitive intelligence (for competitive decks)/octave:generate - Generate content with brand voice control/octave:campaign - Campaign strategy (deck as part of campaign)/octave:enablement - Sales enablement content packaging/octave:pmm - Product marketing collateral/octave:insights - Conversation intelligence for data-driven slides/octave:pipeline - Pipeline data for QBR decksdevelopment
Turn one or more Octave GTM Explorer / Beats reports into a branded, shareable digest with selectable insight scope, evidence depth, and output format. Use when the user asks for a report digest, weekly or monthly insight recap, executive intelligence brief, magazine-style insight story, report deck, or a recurring published summary of Octave insights.
content-media
Product and feature launch planning with full content kit generation across channels and audiences. Use when user says "launch plan", "product launch", "feature announcement", "GTM plan for launch", "launch content kit", or mentions launching something new.
development
A dense internal deal room a rep hands to a champion so they can run the buying-committee sell without you in the room. Quantified business case, stakeholder map with per-seat ammo, objection handling, and a path to yes, rendered as self-contained HTML. Use when user says "champion deal room", "arm my champion", "help my champion sell internally", "internal business case for [deal]", or wants a champion enablement doc. For a customer-facing top-of-funnel page use /octave:microsite; for the formal closing proposal use /octave:proposal.
data-ai
Analyze email threads, call transcripts, and conversations for resonance, adherence to messaging, and competitive differentiation. Use when user says "analyze this call", "how did the email land", "score this thread", "conversation analysis", or pastes conversation content to evaluate.