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_IDbrowser_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:
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
Scan to join WeChat group