Lecture PPT Generator
Convert storyboard markdown into a production-quality PPTX using the html2pptx pipeline with CJK text overflow fix.
Prerequisites
Run bash setup.sh to install all dependencies automatically. Or manually:
- Node.js + npm →
npm install(installs pptxgenjs, playwright, sharp) - Playwright browser →
npx playwright install chromium - Python 3 + pip →
pip3 install -r requirements.txt(installs lxml) html2pptx.jsandthumbnail.pyare bundled inscripts/— no external skill dependency needed
Workflow
Step 1: Parse storyboard
Read the storyboard markdown. Extract per slide:
- Slide number, section, title, type
- Text content (titles, body, card text, labels)
- Visual element instructions (which icons)
- Speaker notes (강사 대본)
See references/storyboard-format.md for input format details.
Step 2: Generate icons
Run scripts/generate-icons.js to create PNG icons in an icons/ directory:
node scripts/generate-icons.js <workspace>/icons
This generates 40 teal-themed SVG→PNG icons in two categories:
- Base (26): flask, shield, lightbulb, cogs, clock, hourglass, chart-up, arrow-r, check, number-1/2/3, etc.
- AI/Tech (14): robot, brain, code, monitor, video, palette, mic, compare, grid6, text-ai, user-dev, shorts, process, star
Add custom icons as needed by extending the svgIcons object.
Step 3: Create HTML slides
Create one HTML file per slide following the light theme design system. See:
- references/design-philosophy.md for design principles, visual balance, anti-patterns (반드시 먼저 읽을 것)
- references/design-system.md for colors, typography, layout rules
- references/html-patterns.md for HTML template patterns per slide type
Critical html2pptx rules:
- All text in
<p>,<h1>-<h6>,<ul>,<ol>— never bare text in<div> - Backgrounds/borders only on
<div>elements, never on<p>or text elements - No
marginon inline<span>elements — use padding or text spacing instead - No bullet symbols (
•,-,*) in<p>text — use<ul><li>instead - Badge/button with colored background: wrap
<p>in a<div>that carriesbackground - Use
class="placeholder"for chart/table areas (rendered gray in HTML, filled by PptxGenJS) - Slide dimensions:
width: 720pt; height: 405pt(16:9) - Font: Arial only (web-safe)
Step 4: Create build script
Create build-pptx.js that:
const pptxgen = require('pptxgenjs');
const html2pptx = require('./scripts/html2pptx.js');
const path = require('path');
const slidesDir = path.join(__dirname, 'slides');
const outFile = '<output-path>.pptx';
// Speaker notes extracted from storyboard
const speakerNotes = [
// Slide 1
`강사 대본 내용...`,
// ... one per slide
];
async function main() {
const pptx = new pptxgen();
pptx.layout = 'LAYOUT_16x9';
pptx.title = '프레젠테이션 제목';
for (let i = 1; i <= N; i++) {
const htmlFile = path.join(slidesDir, `slide${String(i).padStart(2, '0')}.html`);
const { slide, placeholders } = await html2pptx(htmlFile, pptx);
slide.addNotes(speakerNotes[i - 1]);
// Add tables/charts to placeholder areas if needed
if (i === TABLE_SLIDE && placeholders.length > 0) {
const ph = placeholders[0];
slide.addTable([...], { x: ph.x, y: ph.y, w: ph.w, h: ph.h, ... });
}
}
await pptx.writeFile({ fileName: outFile });
}
main().catch(console.error);
For table styling with light theme:
const headerOpts = { fill: { color: 'E8E8E8' }, color: '333333', bold: true, fontSize: 8, align: 'center', valign: 'middle' };
const rowOdd = { fill: { color: 'FFFFFF' }, color: '333333', fontSize: 7, align: 'center', valign: 'middle' };
const rowEven = { fill: { color: 'F8F8F8' }, color: '333333', fontSize: 7, align: 'center', valign: 'middle' };
Step 5: Build PPTX
NODE_PATH=<skill-dir>/node_modules node build-pptx.js
NODE_PATH를 스킬 폴더의 node_modules로 지정해야 html2pptx.js가 playwright 등을 찾을 수 있음.
Step 6: Fix CJK text overflow
Apply the post-processing fix for Korean text rendering differences between Chrome and PowerPoint:
python3 scripts/fix-cjk-overflow.py <raw.pptx> <final.pptx>
This widens all CJK text boxes by 20% width and 15% height, adjusts positions based on alignment, and ensures normAutofit is set. The script is at scripts/fix-cjk-overflow.py.
Step 7: Validate
Generate thumbnails to visually inspect:
python scripts/thumbnail.py <final.pptx> workspace/thumbnails --cols 4
Check for text cutoff, overlap, or positioning issues. If thumbnails fail (no LibreOffice), verify by parsing XML:
# Quick XML verification
import zipfile
from lxml import etree
with zipfile.ZipFile('output.pptx') as z:
for name in sorted(z.namelist()):
if name.startswith('ppt/slides/slide') and name.endswith('.xml'):
print(f"OK: {name}")
Quick Reference
| Step | Command | Output |
|---|---|---|
| Icons | node scripts/generate-icons.js icons/ |
PNG icons |
| Build | node build-pptx.js |
Raw PPTX |
| CJK fix | python3 scripts/fix-cjk-overflow.py raw.pptx final.pptx |
Fixed PPTX |
| Thumbnails | python scripts/thumbnail.py final.pptx |
Visual check |