Shorts Presentation Generator
Overview
This skill creates vertical (9:16 aspect ratio) interactive HTML presentations specifically designed for short-form video content. You screen record the presentation while narrating, then use Opus Clip Pro or direct upload for Shorts/Reels/TikTok.
Key Features:
- •Vertical 9:16 format (1080x1920 optimized)
- •Fast-paced slide design (3-5 seconds per slide)
- •Large, readable text for mobile viewing
- •Bold animations that pop on small screens
- •Click-to-advance for easy recording
- •30-60 second content pacing
CRITICAL: Fact Integrity Rules
Rule 1: NEVER Infer New Facts
- •Only use information explicitly stated in source videos or found in web research
- •NEVER extrapolate, assume, or create new "facts" by combining information
- •If unsure, mark as
[FROM VIDEO]or[NEEDS VERIFICATION]
Rule 2: Source Everything
- •Every fact shown on a slide must have a traceable source
- •Either from the YouTube transcript (with timestamp) or web research (with URL)
- •If you cannot source it, do not include it
Rule 3: Recency Matters
- •Always search for the most recent data (2025-2026)
- •Mark dates on any statistics or data points
- •Outdated facts can go viral for the wrong reasons
Rule 4: Source Attribution Format
Every fact in the presentation must be tagged:
- •
[VERIFIED: Source Name, Date]- Confirmed via web search - •
[FROM VIDEO: Title, Timestamp]- From transcript, not independently verified - •
[USER PROVIDED]- User stated this information
Red Flags - STOP and Verify
If you find yourself including:
- •"Studies show..." → Which study? What year?
- •"Experts say..." → Which expert? What quote?
- •"Millions of..." → Exact number and source?
- •Any statistic → Source URL and date required
Rule 5: ALWAYS Re-Verify Before Generating
DO NOT trust research from earlier in the conversation. Before generating ANY presentation:
- •Re-fetch the primary source - If referencing a GitHub issue, blog post, or article, fetch it AGAIN right before generating slides
- •Check for updates - Issues get closed, bugs get fixed, versions change. What was true 10 minutes ago may not be true now
- •Verify version numbers - ALWAYS confirm the CURRENT latest version and its status. Don't assume old version info is still accurate
- •Cross-reference user's context - If user mentions they're on version X, verify if the issue affects version X specifically
Example of what NOT to do:
- •Research says "bug affects v2.0.75"
- •User says "I'm on v2.0.76"
- •❌ WRONG: Assume v2.0.75 info is still current
- •✅ RIGHT: Search for "v2.0.76 [bug name]" to verify current status
Before generating slides, ALWAYS ask yourself:
- •"Is this the CURRENT version?"
- •"Has this been fixed since my research?"
- •"Did I verify this against the user's specific context?"
Rule 6: Update ALL Outputs When Facts Change
When a fact is corrected or updated:
- •Update the presentation HTML
- •Update the narration script
- •Update the research.md
- •Update any other files referencing that fact
One wrong fact in a viral video destroys credibility.
When to Use
Invoke this skill when:
- •User says "create a short", "make a viral presentation", "shorts presentation"
- •User provides YouTube URLs and wants quick, shareable content
- •User wants to create educational Shorts with animated facts
- •User wants vertical video content for social media
Workflow
Step 1: Collect Input
Accept one or more of:
- •YouTube video URLs (to extract transcripts and facts)
- •A specific topic to research
- •Key points the user wants to convey
Step 2: Fetch YouTube Transcripts (If URLs Provided)
For each video URL, use Playwright MCP with this exact method:
Step 2a: Navigate and Extract with JavaScript (RECOMMENDED)
Use browser_run_code to handle navigation, clicking, and extraction in one reliable call:
// Use this exact code in mcp__plugin_playwright_playwright__browser_run_code
async (page) => {
// Scroll down to load description
await page.evaluate(() => window.scrollBy(0, 400));
await page.waitForTimeout(1000);
// Click expand description button
const expandBtn = await page.$('tp-yt-paper-button#expand');
if (expandBtn) {
await expandBtn.click();
await page.waitForTimeout(500);
}
// Click "Show transcript" button
const showTranscriptBtn = await page.$('button[aria-label="Show transcript"]');
if (showTranscriptBtn) {
await showTranscriptBtn.click();
await page.waitForTimeout(1500);
}
// Extract transcript segments using Playwright's querySelectorAll method
const segments = await page.locator('ytd-transcript-segment-renderer').evaluateAll(els =>
els.map(el => {
const time = el.querySelector('.segment-timestamp')?.innerText?.trim() || '';
const text = el.querySelector('.segment-text')?.innerText?.trim() || '';
return '[' + time + '] ' + text;
}).join('\n')
);
return segments || 'Transcript not found';
}
Step 2b: Alternative - Manual Click Method
If the JavaScript method fails, use manual clicks:
- •
browser_navigatetohttps://www.youtube.com/watch?v=VIDEO_ID - •
browser_snapshotto get page state - •Look for "Show transcript" button ref in snapshot (usually in description area)
- •
browser_clickwith the exact ref (e.g.,ref=e3960) - •
browser_snapshotagain to see transcript panel - •Use
browser_run_codeto extract just the transcript text
CRITICAL: Do NOT use browser_snapshot alone - the transcript text is in buttons, not plain text. Always use JavaScript to extract the actual segment content from ytd-transcript-segment-renderer elements.
Common Issues:
- •If snapshot shows transcript panel but no text: Use JavaScript to extract
- •If "Show transcript" button not visible: Scroll down and expand description first
- •If transcript not loading: Wait longer (1500ms+) after clicking
Extract from each video:
- •Video title
- •Key claims/facts with timestamps
- •Statistics mentioned
- •Quotes that could be used
Step 3: Web Research for Verification
Use WebSearch to:
- •Verify any numerical claims from the video
- •Find additional recent data on the topic
- •Get official sources for credibility
Search Strategy:
- •Use
site:operators for authoritative sources - •Always include current year in searches
- •Look for the most recent data available
Source Priority:
- •Official sources (government, company reports)
- •Major news outlets (Reuters, Bloomberg, AP)
- •Industry publications
- •Original video (clearly attributed)
Step 4: Ask Clarifying Questions
Question 1: Content Focus
"What's the main hook for this Short?" Header: "Hook" Options: - Surprising fact reveal - Myth vs Reality - Quick tutorial/tip - Comparison (A vs B) - Story/Timeline
Question 2: Slide Count
"How many slides (aim for 30-60 seconds total)?" Header: "Length" Options: - 5-7 slides (30 seconds - punchy) - 8-10 slides (45 seconds - standard) [Recommended] - 11-15 slides (60 seconds - detailed)
Question 3: Visual Style
"What visual style?" Header: "Style" Options: - Bold & Minimal (large text, high contrast) [Recommended] - Data-focused (stats, numbers, charts) - Comparison view (split screen style) - Story sequence (narrative flow)
Question 4: Theme
"Color theme?" Header: "Theme" Options: - Dark Mode (black/teal) [Recommended for screen recording] - Light Mode (white/blue) - High Energy (dark/orange-red) - Professional (dark/green)
Step 4.5: VERIFICATION CHECKPOINT (REQUIRED)
Before generating slides, present facts to user for approval:
## 🔒 FACT VERIFICATION CHECKPOINT
I found these facts from analysis and research:
### ✅ VERIFIED FACTS (confirmed via web search)
| Fact | Source | Date |
|------|--------|------|
| [fact] | [source URL] | [date] |
### 📺 VIDEO CLAIMS (from transcript, not independently verified)
| Claim | Video | Timestamp |
|-------|-------|-----------|
| [claim] | [video title] | [MM:SS] |
### ❌ COULD NOT VERIFY
| Claim | Search Attempted | Result |
|-------|------------------|--------|
| [claim] | [what I searched] | Not found |
---
**Which facts should I include in the Short?**
- I recommend only using ✅ VERIFIED facts
- 📺 VIDEO CLAIMS can be included with attribution ("According to [video]...")
- ❌ UNVERIFIED facts should NOT be used
Select the facts you want featured (by number):
Wait for user to select which facts to include before generating slides.
Step 5: Generate Slide Content
Create 5-15 slides following this structure:
Slide 1: Hook (0-3 sec)
LARGE BOLD TEXT [Attention-grabbing statement or question]
Slides 2-N: Content (3-5 sec each)
KEY POINT [Supporting detail] [Source indicator if applicable]
Final Slide: CTA or Punchline (3-5 sec)
[Memorable conclusion] [Call to action if appropriate]
Step 6: Generate HTML Presentation
Create a vertical HTML file optimized for:
- •1080x1920 resolution (9:16)
- •Large, bold typography (minimum 48px)
- •High contrast colors
- •Simple animations (fade, scale, slide)
- •Touch/click advancement
- •No distracting elements
Step 7: Save and Provide Instructions
IMPORTANT: Shorts go in the Ideas folder with "SHORTS - " prefix.
Save to: ~/YT/Ideas/SHORTS - [Topic]/presentation.html
Provide recording instructions:
Your Shorts presentation is ready! **File:** ~/YT/Shorts/[Topic]/presentation.html **How to Record:** 1. Open in Chrome 2. Press F11 for fullscreen 3. Resize Chrome window to 1080x1920 (or use DevTools mobile view) 4. Start OBS/screen recording 5. Click to advance each slide while narrating 6. Each slide = 3-5 seconds of content **Tips for Recording:** - Speak with energy - shorts need high engagement - Match your voice to the slide transitions - Keep total length under 60 seconds - The hook (slide 1) is crucial - nail it **After Recording:** - Upload directly to YouTube Shorts, TikTok, Reels - Or use Opus Clip Pro for auto-captions and effects
Shorts-Optimized Slide Types
Hook Slide
<div class="slide hook-slide"> <h1 class="hook-text">[HOOK TEXT]</h1> <p class="hook-subtext">[Optional subtext]</p> </div>
- •Largest text size
- •Centered, bold
- •Immediate attention grab
Fact Slide
<div class="slide fact-slide"> <p class="fact-label">[LABEL like "FACT" or "DID YOU KNOW"]</p> <h2 class="fact-text">[The fact]</h2> <p class="fact-source">[Source]</p> </div>
- •Clear hierarchy
- •Source visible but not dominant
Number Reveal Slide
<div class="slide number-slide"> <p class="number-label">[Context]</p> <h1 class="big-number" data-animate="count">[NUMBER]</h1> <p class="number-unit">[Unit or description]</p> </div>
- •Animated number counter
- •Dramatic reveal effect
Comparison Slide
<div class="slide compare-slide">
<div class="compare-item wrong">
<span class="compare-icon">❌</span>
<p>[Wrong/Myth/Before]</p>
</div>
<div class="compare-item right">
<span class="compare-icon">✅</span>
<p>[Right/Truth/After]</p>
</div>
</div>
- •Clear visual distinction
- •Stacked vertically for mobile
Quote Slide
<div class="slide quote-slide"> <div class="quote-mark">"</div> <p class="quote-text">[Quote]</p> <p class="quote-author">— [Author]</p> </div>
- •Large quote marks
- •Emphasis on the words
List Slide
<div class="slide list-slide">
<h2 class="list-title">[Title]</h2>
<ul class="shorts-list">
<li data-reveal="1">[Item 1]</li>
<li data-reveal="2">[Item 2]</li>
<li data-reveal="3">[Item 3]</li>
</ul>
</div>
- •Items reveal one by one
- •3-5 items max per slide
CTA Slide
<div class="slide cta-slide">
<h2 class="cta-text">[Call to action]</h2>
<p class="cta-subtext">[Supporting text]</p>
<div class="cta-icons">
<span>👆 Follow</span>
<span>💬 Comment</span>
<span>🔄 Share</span>
</div>
</div>
- •Clear action request
- •Platform-appropriate icons
Theme Options for Shorts
Dark Mode (Default)
--bg-primary: #000000; --bg-secondary: #1a1a1a; --text-primary: #ffffff; --text-secondary: #a0a0a0; --accent: #00d4aa;
Light Mode
--bg-primary: #ffffff; --bg-secondary: #f5f5f5; --text-primary: #000000; --text-secondary: #666666; --accent: #3b82f6;
High Energy
--bg-primary: #0a0a0a; --bg-secondary: #1a1a1a; --text-primary: #ffffff; --text-secondary: #a0a0a0; --accent: #ff6b35;
Professional
--bg-primary: #0f172a; --bg-secondary: #1e293b; --text-primary: #f8fafc; --text-secondary: #94a3b8; --accent: #22c55e;
Animation Presets for Shorts
Slide In
.slide { animation: slideIn 0.3s ease-out; }
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
Scale Pop
.slide { animation: scalePop 0.3s ease-out; }
@keyframes scalePop {
from { transform: scale(0.8); opacity: 0; }
to { transform: scale(1); opacity: 1; }
}
Fade Up
.slide { animation: fadeUp 0.3s ease-out; }
@keyframes fadeUp {
from { transform: translateY(50px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
Number Count
// For dramatic number reveals
function animateNumber(el, target, duration = 800) {
let current = 0;
const increment = target / (duration / 16);
const timer = setInterval(() => {
current = Math.min(current + increment, target);
el.textContent = formatNumber(Math.floor(current));
if (current >= target) clearInterval(timer);
}, 16);
}
Content Pacing Guide
| Slide Type | Duration | Purpose |
|---|---|---|
| Hook | 2-3 sec | Grab attention immediately |
| Fact/Point | 4-5 sec | Deliver key information |
| Number Reveal | 3-4 sec | Dramatic stat reveal |
| Comparison | 5-6 sec | Show contrast clearly |
| Quote | 4-5 sec | Let quote sink in |
| List (per item) | 2 sec each | Quick reveals |
| CTA | 3-4 sec | Clear next action |
Total target: 30-60 seconds
Example: Shorts from YouTube Analysis
User: Create a short from this video about AI productivity
https://youtube.com/watch?v=ABC123
Claude: [Fetches transcript via Playwright MCP]
[Identifies key facts and statistics]
[Verifies claims via WebSearch]
I found 5 key facts from this video:
1. "AI tools save an average of 2 hours per day" - [VERIFIED: McKinsey 2024]
2. "ChatGPT has 200M weekly users" - [VERIFIED: OpenAI 2024]
3. "40% of workers use AI secretly" - [FROM VIDEO - needs verification]
4. "Productivity up 35% with AI" - [PARTIALLY VERIFIED: varies by study]
5. "AI will replace 30% of jobs" - [DISPUTED: estimates vary widely]
Which facts would you like to feature in the Short?
[User selects facts 1, 2, 4]
[Asks clarifying questions about style]
Generating your Shorts presentation...
**Slides Created:**
1. Hook: "AI is changing EVERYTHING about work"
2. Number: "2 HOURS saved per day with AI tools"
3. Source: "According to McKinsey Research 2024"
4. Number: "200 MILLION people use ChatGPT weekly"
5. Number: "35% productivity boost with AI"
6. CTA: "Follow for more AI insights"
**File:** ~/YT/Shorts/AI Productivity Facts/presentation.html
**Recording Tips:**
- Hook with energy: "Did you know AI can give you 2 extra hours every day?"
- Pause on numbers for impact
- End with enthusiasm for the CTA
- Total time: ~35 seconds
Folder Structure
~/YT/Shorts/ ├── [Topic Name 1]/ │ ├── presentation.html │ ├── research.md (sources and verification) │ └── script-notes.md (optional talking points) ├── [Topic Name 2]/ │ └── ...
Integration with Opus Clip Pro
After recording the screen with your narration:
- •Export as vertical video (1080x1920)
- •Upload to Opus Clip Pro
- •Let it add auto-captions
- •Apply effects/transitions
- •Auto-post to all platforms
The presentation provides the visual backbone - your voice and Opus Clip's captions complete the package.
Safety Reminders
- •Double-check all numbers before recording
- •Date your statistics - add "as of 2025" to slides if needed
- •Cite sources verbally when recording ("According to McKinsey...")
- •Don't mix sources - clearly separate video claims from research
- •When in doubt, leave it out - one wrong fact can tank credibility
Troubleshooting
Transcript Extraction Fails
Solutions (try in order):
- •Check video has captions: Not all videos have CC
- •Fallback to Python script:
bash
cd ~/YT/_Config/scripts source .venv/bin/activate python fetch_youtube.py "VIDEO_URL" --format markdown
- •Manual fallback: Ask user to provide key facts directly
WebSearch Doesn't Find Verification
- •Try different search terms: Use company/organization names directly
- •Check official sources: Go directly to company websites, government sites
- •Mark as unverified: If no source found, do NOT include in slides
- •Ask user: "I couldn't verify [claim]. Do you have a source, or should I exclude it?"
Vertical Format Display Issues
- •Chrome DevTools: Press F12 → Toggle device toolbar → Select custom 1080x1920
- •OBS Setup: Create scene with 1080x1920 canvas, window capture Chrome
- •Preview: Always preview at actual size before recording
CRITICAL: HTML Template for Vertical Presentations
You MUST use this EXACT structure for all shorts presentations. Do NOT deviate.
Complete HTML Template (REQUIRED)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>[PRESENTATION TITLE]</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
background: #000;
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", Roboto, sans-serif;
}
/* 9:16 Container - centered and scaled to fit viewport */
.container {
position: absolute;
top: 50%;
left: 50%;
width: 1080px;
height: 1920px;
background: #0a0a0a;
transform-origin: center center;
}
/* Progress bar - thick and visible */
.progress {
position: absolute;
top: 0;
left: 0;
height: 12px;
background: linear-gradient(90deg, #00d4aa, #00a080);
z-index: 1000;
transition: width 0.3s ease;
}
/* Slide counter - large and clear */
.counter {
position: absolute;
bottom: 80px;
right: 60px;
font-size: 48px;
font-weight: 700;
color: rgba(255,255,255,0.7);
z-index: 1000;
font-variant-numeric: tabular-nums;
}
/* Slides */
.slide {
position: absolute;
top: 0;
left: 0;
width: 1080px;
height: 1920px;
display: none;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100px 70px;
text-align: center;
color: #fff;
}
.slide.active {
display: flex;
animation: fadeIn 0.3s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
/* [ADD YOUR CUSTOM STYLES HERE] */
</style>
</head>
<body>
<div class="container" id="container">
<div class="progress" id="progress"></div>
<div class="counter" id="counter">1 / [TOTAL]</div>
<!-- Slides go here -->
<div class="slide active">
<!-- Slide 1 content -->
</div>
<div class="slide">
<!-- Slide 2 content -->
</div>
<!-- More slides... -->
</div>
<script>
const slides = document.querySelectorAll('.slide');
const progress = document.getElementById('progress');
const counter = document.getElementById('counter');
const container = document.getElementById('container');
let current = 0;
const total = slides.length;
// Scale container to fit viewport
function scaleContainer() {
const vw = window.innerWidth;
const vh = window.innerHeight;
const scale = Math.min(vw / 1080, vh / 1920);
container.style.transform = `translate(-50%, -50%) scale(${scale})`;
}
function update() {
// Update slides
slides.forEach((s, i) => {
s.classList.toggle('active', i === current);
});
// Update progress bar
const pct = ((current + 1) / total) * 100;
progress.style.width = pct + '%';
// Update counter
counter.textContent = (current + 1) + ' / ' + total;
}
function next() {
if (current < total - 1) {
current++;
update();
}
}
function prev() {
if (current > 0) {
current--;
update();
}
}
// Click to advance
container.addEventListener('click', next);
// Keyboard
document.addEventListener('keydown', e => {
if (e.key === 'ArrowRight' || e.key === ' ' || e.key === 'Enter') {
e.preventDefault();
next();
} else if (e.key === 'ArrowLeft') {
e.preventDefault();
prev();
} else if (e.key === 'Home') {
current = 0;
update();
} else if (e.key === 'End') {
current = total - 1;
update();
}
});
// Touch support
let touchStartX = 0;
container.addEventListener('touchstart', e => {
touchStartX = e.touches[0].clientX;
});
container.addEventListener('touchend', e => {
const diff = touchStartX - e.changedTouches[0].clientX;
if (Math.abs(diff) > 50) {
if (diff > 0) next();
else prev();
}
});
// Init
scaleContainer();
window.addEventListener('resize', scaleContainer);
update();
</script>
</body>
</html>
MANDATORY Requirements
| Requirement | Details |
|---|---|
| Container class | Must be .container (NOT .presentation-container) |
| Container ID | Must have id="container" for JavaScript |
| Scaling | Use JavaScript scaleContainer() function (NOT CSS media queries) |
| Progress bar | At TOP of container, gradient color, 12px height |
| Slide counter | At BOTTOM RIGHT, format "1 / 9", 48px font |
| Slide dimensions | Fixed width: 1080px; height: 1920px (NOT 100%) |
| Slide padding | padding: 100px 70px |
| Animation | Use fadeIn with scale (NOT slideIn or other) |
Common Mistakes to AVOID
| Mistake | Why It Breaks | Correct Approach |
|---|---|---|
Using .presentation-container | Wrong class name | Use .container |
| CSS media queries for scaling | Inconsistent across browsers | Use JavaScript scaleContainer() |
| Progress dots at bottom | Wrong design pattern | Use progress bar at TOP |
| Counter at top right | Wrong position | Counter at BOTTOM RIGHT |
width: 100% on slides | References viewport, not container | Use width: 1080px |
height: 100% on slides | References viewport, not container | Use height: 1920px |
Missing id="container" | JavaScript won't work | Add the ID |
Pre-Generation Checklist
Before generating HTML, verify:
- • Container uses
.containerclass withid="container" - • JavaScript
scaleContainer()function is included - • Progress bar at top with gradient
- • Slide counter at bottom right in "X / Y" format
- • Slides have
position: absolute - • Slides have fixed pixel dimensions (1080x1920)
- • Slide padding is
100px 70px - •
fadeInanimation with scale transform
Recording Tips
- •Consistent timing: Practice clicking through at 3-5 second intervals
- •Voice matching: Script what you'll say for each slide before recording
- •Energy level: Shorts need higher energy than long-form content
- •Re-record if needed: Better to do multiple takes than publish subpar content