Keynote Slides
Assets
assets/keynote-slides.htmlholds the single-file slide deck template.references/brand-guidelines.mdcaptures brand tokens, typography, and image style guidance.references/gemini-media.mddocuments the Gemini nano banana and Veo media settings.
Workflow
-
Resolve entity + detect content-db. Read
deck.json→entityfield; fall back to<section data-entity="...">on the active slide; then tobrands.jsdefault entity (the entity whose export key is"default", or the single entity in the file). Check whethercontent-db/<entity>/exists alongsidebrands.js. If it does and is well-formed, content-db mode is active — load relevant atoms before generating any content. If it does not exist or is malformed, proceed normally with no message. See the Content Database section for the full protocol. -
Run the deck bootstrap to create a deck folder:
scripts/new-deck.sh example-pitch --entity northwind --title "Example Pitch" --type pitch
- Update
decks/brands.jswhen brand tokens change. - Edit
decks/<deck-id>/index.htmland duplicate slides inside<main id="deck">, keeping eachdata-titleunique. - Use layout classes (
layout-title,layout-split,layout-grid,layout-metrics,layout-quote) to keep spacing consistent. - Apply
revealplus--reveal-indexto stagger key elements.
Entities
- Use the generator panel to select the active entity profile.
- Add
data-entity="entity-id"on a slide to override the global profile for that slide. - Add
?entity=entity-idto the URL for a quick switch. - Use
mediaPromptPrefixinbrandProfilesto keep Gemini media outputs on brand.
Deck storage
decks/<deck-id>/index.htmlis the editable deck file.decks/<deck-id>/deck-config.jsstores deck metadata (entity, title, resources).decks/<deck-id>/deck.jsonstores the same metadata in JSON form.decks/<deck-id>/slides.mdis for draft copy and notes.decks/<deck-id>/resources/assets/holds logos, images, and media inputs.decks/<deck-id>/resources/materials/holds briefs, pricing docs, P&L inputs, and outlines.
PMF Panel Integration
Export PMF Panel findings as deck input materials:
# From pmf-panel directory
.claude/export-deck-brief.sh <scenario-id>
# Copy to deck materials
cp scenarios/<scenario-id>/deck-brief.md \
../keynote-slides-skill/decks/<deck-id>/resources/materials/pmf-brief.md
The brief includes diagnosis, scenarios, 30/60/90 plan, and specialist perspectives ready for narrative engine ingestion.
Collaboration
- Co-author the narrative: propose headlines, POV, and slide ordering based on
deckTypeand entity preferences. - Keep the brief in
resources/materials/brief.mdand capture evolving preferences indeck.jsonordecks/brands.js. - Use concise headline options (3-5 variants) and confirm direction before building slides.
Review loop
- Use the Chrome Devtools MCP tools to capture a snapshot/screenshot and review layout.
- Check hierarchy, alignment, spacing rhythm, and contrast; then adjust copy and spacing.
- Use the generator panel for brand-aware media, then re-check balance and whitespace.
- Register new content-db atoms (if active). After review, write new atoms to
content-db/<entity>/for any claims (cl###), copy strings (cp###), or assets (as###) introduced during the build. Runnode content-db/validate.js(or equivalent). The output package is not complete until validation exits 0. Do not modify existing atoms — add avl###validation record and mark the originalstatus: disputedif wording conflicts.
Templates
- Copy markup from the
<template>blocks at the bottom of the file. - Replace placeholders with branded copy, numbers, and visuals.
Media generation
- Add
data-genanddata-promptto<img>or<video>elements. - Open the generator panel with
gor theGenbutton. - Save the API key and model settings to localStorage (never commit keys).
- For image-to-image or image-to-video, load a base image in the panel.
- Run "Generate slide" or "Generate all" and review outputs.
Model-Mediated Image Acquisition
Use the /acquire-images skill (see skills/acquire-images.md) to populate slides with visuals.
Claude decides whether to generate (Gemini) or search (stock photos) for each slide:
| Content Type | Decision | Why | |--------------|----------|-----| | Diagrams, flowcharts | GENERATE | Custom layouts, brand colors | | Data visualizations | GENERATE | Precise data representation | | Real-world photos | SEARCH | Authentic people, places | | Team/people shots | SEARCH | Realistic human photos | | Abstract concepts | GENERATE | Metaphorical, brand-styled | | Branded hero images | HYBRID | Search base + AI overlay |
Search sources: Unsplash, Pexels, Google Custom Search.
Attribution: Downloaded images tracked in resources/materials/image-credits.json.
See skills/acquire-images.md for the full workflow.
Preview
scripts/serve-decks.sh
Then open http://<tailscale-ip>:8921/decks/<deck-id>/index.html.
Speaker notes
- Add per-slide notes with a hidden block:
<aside class="slide-notes">Speaker notes here.</aside> - Toggle the notes panel with the "Notes" button or press
n. - Append
?notes=1to open notes by default. - Use "Export notes" to download a markdown file.
Animation + SVG
- Use
data-animfor lightweight entrance animations (fade, slide-up, slide-left, slide-right, scale-in). - Set
--anim-delayto stagger; avoid mixing withrevealon the same element. - Disable animation with
?motion=offor rely onprefers-reduced-motion. - Inline SVG diagrams use
.diagramanddata-media="svg":<svg class="diagram" data-media="svg" viewBox="0 0 800 450" role="img" aria-label="Diagram"></svg> - Keep media lanes explicit:
data-gen= Gemini only (optionaldata-media="gemini").- Inline SVG = no
data-gen. - Static images/videos = no
data-gen.
Micro Animations
Micro animations are small decorative accent elements that add subtle motion to slides without distracting from content.
What micro animations ARE:
- Small accent lines that expand/draw next to headlines
- Subtle decorative strokes or shapes that pulse gently
- Tiny visual flourishes positioned near text (not on text)
- CSS-driven, lightweight, and unobtrusive
What micro animations are NOT:
- Large SVG graphics or overlays covering slide areas
- Animations applied directly to text (no flashing, glowing, or bouncing text)
- Complex particle systems or heavy motion graphics
- Anything that competes with or obscures content
Implementation:
<!-- Accent line after a headline -->
<h1 class="title">Your headline here</h1>
<span class="accent-line"></span>
Available classes:
.accent-line— 80px amber line that expands from left, then pulses.accent-line.long— 120px version for major headlines
Behavior:
- Line draws in from left (0.8s ease-out) when slide becomes active
- Then gently pulses (opacity + slight scale) on a 4s cycle
- Respects
prefers-reduced-motionand?motion=off
When to use:
- Title slides (layout-title) to add visual interest
- Key message slides where you want emphasis
- Sparingly — 3-4 slides per deck maximum
Copy editor
- Open
decks/<deck-id>/editor.htmlin a second window to edit copy without touching HTML. - Use the editor "Open deck" button to connect and update the live preview.
- For existing decks, copy the template first:
cp skills/keynote-slides/assets/keynote-editor.html decks/<deck-id>/editor.html - Edits are stored in localStorage; export JSON from the editor for handoff.
PDF export
- Use the browser print dialog and "Save as PDF".
- Enable background graphics for gradients and color fills.
- The template includes print styles to paginate each slide.
- CLI option:
node scripts/export-pdf.js decks/<deck-id> --out /tmp/<deck-id>.pdf
Navigation
- Arrow keys, PageUp/PageDown, Space.
- Home/End for first or last slide.
- Use
#slide-titlehash navigation for direct jumps.
Review Mode / Feedback System
Enable reviewers to leave comments on deck elements for collaborative feedback.
Entering Review Mode
- Click the "Review" button in the bottom toolbar (next to Gen)
- Press
rkey to toggle review mode - Add
?review=1to the URL to start in review mode
Adding Comments
- In review mode, hover over elements to see them highlighted
- Click any commentable element (titles, text, cards, metrics, media frames)
- Or select text within an element to comment on specific wording/typos
- First-time commenters enter name and email (stored in session)
- Type feedback in the popover and click "Add Comment"
- A numbered badge (①②③) appears on commented elements for easy reference
Viewing Comments
- Press
cor click the sidebar toggle to open the comment sidebar - Comments are grouped by slide
- Click "Go to slide" to navigate to the commented element
- Mark comments as resolved or delete them
Exporting Feedback
From the comment sidebar:
- Export JSON - Downloads
comments-<deck-id>.jsonfor backup or import - Export MD - Downloads markdown summary for sharing or Claude iteration
Feedback Viewer Page
Use assets/feedback-viewer.html to review all feedback outside the deck:
- Open
feedback-viewer.htmlin a browser - Load a
comments.jsonfile or enter a URL - Filter by open/resolved status
- Mark comments as resolved
- Export updated JSON or markdown
Add ?url=<path-to-json> to auto-load comments.
Comment Data Structure
Comments are stored in localStorage keyed by deck ID. Export structure:
{
"deckId": "example-pitch",
"nextNumber": 4,
"comments": [
{
"id": "c_1706123456789_abc123",
"number": 1,
"slideIndex": 2,
"slideTitle": "Our Solution",
"elementSelector": "[data-comment-target='headline']",
"elementText": "First 50 chars of element...",
"selectedText": "specific phrase",
"comment": "This needs more specificity",
"author": {
"name": "Sarah Chen",
"email": "sarah@example.com"
},
"createdAt": "2024-01-24T10:30:00Z",
"resolved": false
}
]
}
number: Sequential comment number (①②③) for easy reference in feedbackselectedText: If reviewer selected specific text, captures that selection (null otherwise)
Element Targeting
For precise comment targeting, add data-comment-target attributes:
<h2 data-comment-target="solution-headline">Our Solution</h2>
<p data-comment-target="value-prop-1">We reduce costs by 40%...</p>
Elements without explicit targets use a generated CSS selector path.
Narrative Engine Integration
For content-driven deck creation, use the Narrative Engine workflow that matches your material to proven storytelling frameworks.
Reference Files
references/narrative-engine/narrative-arcs.md— Beat-by-beat structures for 10 narrative arcsreferences/narrative-engine/framework-selection.md— Selection matrix by audience/purpose/contentreferences/narrative-engine/framework_selection_guide.md— Deep pairing guidance for arcs + frameworksreferences/narrative-engine/communication-frameworks.md— 7 efficiency-optimized frameworksreferences/narrative-engine/checklists.md— Quality gates for narrative + copy reviewreferences/narrative-engine/agent-reference-*.md— Agent-specific frameworks for review
Workflow: Narrative Build
- Ingest resources: Run
node scripts/ingest-resources.js decks/<deck-id>to read all materials- Or use
node scripts/narrative-build.js decks/<deck-id>to prepare model-mediated prompts 1a. Load content-db atoms (if active). If content-db mode is active, pullcopy.mdandclaims.mdatoms for the resolved entity. Filter atoms byaudiencetag if present. Surface any atom with a non-nullgatevalue before proceeding — do not include gated content without user confirmation. If content-db is not active, skip this step.
- Or use
- Focal discovery + discovery: Align on the one point, then answer 5 questions (audience, purpose, content type, tone, reveal)
- Density + framework match: Choose density mode, then get 2-3 recommendations with content mapped to structure
- Deck generation: Build slides with source attribution tags. If content-db is active: use each claim's exact approved text — do not paraphrase. For any claim or copy string not found in the db, pause and ask: "That claim isn't in
content-db/<entity>/claims.md— want me to register it as unverified, or use the closest approved atom?" Do not silently include or skip unapproved content. - Review panel: 5 agents + Director synthesize feedback
Discovery Questions
| Question | Options | |----------|---------| | Audience | Executive, Technical, Investors, Skeptics, General, Mixed | | Purpose | Persuade, Inform, Inspire, Align, Report, Defend, Entertain | | Content type | Research, Strategy, Origin story, Post-mortem, Pattern insight, etc. | | Tone | Authoritative, Provocative, Warm, Urgent, Balanced, Visionary | | Reveal potential | Yes (has surprise), No (straightforward), Help me find one |
Framework Selection Quick Reference
| If your content has... | Consider... | |------------------------|-------------| | A genuine surprise | The Prestige or Mystery Box | | Multiple stakeholder views | Rashomon | | A transformation story | Hero's Journey | | Future vision | Time Machine | | Root cause analysis | Columbo | | Strategy/roadmap | The Heist | | Paradigm shift | Trojan Horse |
5-Agent Review Panel
| Agent | Lens | Key Question | |-------|------|--------------| | Audience Advocate | Target audience persona | "Does this land for [audience]?" | | Comms Specialist | Messaging, emotion, PR risk | "Is this tight and bulletproof?" | | Visual Designer | Metaphor coherence, S.T.A.R. moments | "What visual makes this unforgettable?" | | Critic | Pacing, weak links, efficacy | "What's the weakest link?" | | Content Expert | Accuracy, logic, sources | "Can every claim be defended?" |
Stress Test Panel (Optional)
After the 5-agent review, optionally stress-test with stakeholder personas auto-selected by content type:
| Persona | Questions | Best For | |---------|-----------|----------| | Engineer | "How does this actually work?" | Technical proposals, product launches | | Skeptic | "Why should I believe this?" | Bold claims, paradigm shifts | | Risk Officer | "What could go wrong?" | Strategy, transformation, investment | | CFO | "What are the numbers?" | Pitches, business cases, ROI claims | | Lawyer | "What's the exposure?" | Policy, compliance, external-facing | | Conservative | "Why change what's working?" | Change management | | COO | "Would this actually work?" | Execution plans, go-to-market |
The Director triages findings into Must Fix, Should Fix, and Could Fix categories.
Source Attribution Tags
| Tag | Meaning |
|-----|---------|
| [DIRECT] | Verbatim from source material |
| [PARAPHRASE] | Restated ideas |
| [ELABORATED] | Expanded concept |
| [SYNTHESIZED] | Combined multiple sources |
| [GENERATED] | New content for flow |
Headline Rules
- Image & Action: Concrete nouns + strong transitive verbs; avoid "is/are"
- Tension & Turn: Because/Therefore, Not/But, Before/After
- Cadence: 8-14 words; two-beat rhythm
- Specific Anchors: Time/place/actor/number in every third headline
- Power verbs: tilts, unseats, ignites, drains, compounds, unlocks, anchors, accelerates
- Metaphor family: One per deck (journey OR ecology OR weather, etc.)
See /docs/integrated-architecture.md for full technical details.
Content Database
A modular, approved-content management layer for any project using keynote-slides. When a content-db/<entity>/ directory exists alongside brands.js, agents automatically load and enforce approved atoms. When it does not exist, the skill runs exactly as before — no config, no warnings.
Directory Structure
<deck-repo>/
├── brands.js ← entity source of truth (unchanged)
├── content-db/
│ └── <entity>/ ← one directory per entity
│ ├── README.md ← schema reference + agent protocol
│ ├── claims.md ← cl### atoms — stats, benchmarks, data points
│ ├── validation.md ← vl### atoms — experimental evidence blocks
│ ├── assets.md ← as### atoms — images, video, SVG with provenance
│ ├── copy.md ← cp### atoms — approved text passages
│ ├── brand.md ← br### atoms — color tokens, typography
│ └── layouts.md ← ly### atoms — approved slide structures
└── <deck-id>/ ← decks alongside (unchanged)
content-db/ always lives next to brands.js. Multi-entity repos have one subdirectory per entity.
Entity Resolution
Resolve the active entity in this order:
deck.json→entityfield<section data-entity="...">on the active slidebrands.js→ the entity whose export key is"default", or the single entity in the file. If multiple entities exist without a"default"key, surface the ambiguity — do not guess.
Detection
resolve entity
→ content-db/<entity>/ exists and is well-formed?
→ YES: load relevant atom files, activate compliance
→ MALFORMED: log warning, proceed without compliance
→ NO: proceed as normal, no message
| Operation | Atom files loaded |
|-----------|------------------|
| Narrative planning | copy.md, claims.md |
| Full build | all six files |
| Targeted edit | only types relevant to the change |
Compliance Rules
- Read before write. Load relevant atoms before generating content. Never re-derive brand colors or claim text if an atom already exists.
- Surface unapproved content (Build and Edit only — not planning). If a claim or copy string is not in the db (different number, source, or framing = new claim; minor rewording = same), pause: "That claim isn't in
content-db/<entity>/claims.md— want me to register it as unverified, or use the closest approved atom?" - Register new atoms. After any build or edit, write atoms for all claims (
cl###), copy strings (cp###), and assets (as###) introduced. Runnode content-db/validate.js. Output is not complete until exit 0. - Never modify existing atoms. If content conflicts with an existing atom, add a
vl###validation record and updatestatus: disputedin the original. Surface the conflict to the user.
Atom Prefixes
All new atoms use a two-letter prefix + zero-padded three-digit number. Existing atoms with single-letter prefixes are grandfathered.
| File | Prefix | Contents |
|------|--------|----------|
| claims.md | cl### | Stats, benchmarks — status: validated \| disputed \| unverified |
| validation.md | vl### | Experimental evidence — experiment_type, result, institution |
| assets.md | as### | Images, video, SVG — file, deck, type, used_in |
| copy.md | cp### | Approved text passages — concept, audience_level, tone, variants |
| brand.md | br### | Color tokens, typography — element, css_var, value, usage_rules |
| layouts.md | ly### | Slide structures — slide_type, css_classes, js_required, data_density |
Each atom is a ## <id> heading with bullet-field body. Full schema in content-db/<entity>/README.md.
Bootstrap
The skill does not scaffold a content-db unprompted. If a user asks why content-db is not active, explain the directory is absent and offer to create it. Only scaffold if the user says yes.
Bootstrap steps (when approved):
- Create
content-db/<entity>/directory - Create six empty atom files with schema header comments
- Create
README.mdwith schema reference and compliance rules - Offer (separately) to extract initial atoms from existing deck HTML
If the user declines, proceed in no-compliance mode and do not raise the topic again in the same session.