Slide Rendering
Deckyard can render slides server-side for exports and previews.
Overview
Section titled “Overview”Server-side rendering enables high-quality exports and previews without requiring a browser on the client. Deckyard uses Puppeteer (headless Chromium) to render slides as images.
PNG Rendering
Section titled “PNG Rendering”How It Works
Section titled “How It Works”- HTML Generation - Slide content + CSS + fonts assembled into HTML
- Browser Rendering - Puppeteer opens the HTML
- Screenshot - Viewport captured as PNG buffer
- Return - Buffer returned for saving or streaming
Render Process
Section titled “Render Process”// Internal rendering flowconst buffer = await renderSlideToPngBuffer(repoRoot, slide, { scale: 2, // 2x for retina quality theme: themeObject});Dimensions
Section titled “Dimensions”| Setting | Value |
|---|---|
| Native viewport | 1600 x 900 |
| Aspect ratio | 16:9 |
| Scale options | 1x, 2x, 3x |
| Output (2x) | 3200 x 1800 |
Scale Options
Section titled “Scale Options”| Scale | Output Size | Use Case |
|---|---|---|
| 1x | 1600 x 900 | Preview, thumbnails |
| 2x | 3200 x 1800 | Standard export |
| 3x | 4800 x 2700 | High-res print |
OG Image Generation
Section titled “OG Image Generation”Purpose
Section titled “Purpose”Generate social media preview images for shared presentations.
Dimensions
Section titled “Dimensions”| Property | Value |
|---|---|
| Canvas | 1200 x 630 |
| Slide area | Max 1120 x 630 |
| Background | #121212 (dark gray) |
Process
Section titled “Process”- Render first meaningful slide at 1600x900
- Resize to fit within OG dimensions
- Center on dark canvas
- Optionally add author overlay
- Return 1200x630 PNG
Author Overlay
Section titled “Author Overlay”Optional branding in top-right corner:
await generateOgPreview(repoRoot, slide, theme, { showAuthor: true, authorInfo: { name: 'John Doe', imageUrl: 'https://...' }});Print Rendering
Section titled “Print Rendering”PDF Export
Section titled “PDF Export”For PDF exports, slides are rendered and assembled into a document:
- Each slide rendered as PNG
- PNGs combined into PDF
- Optional speaker notes added
- Multiple layouts supported (1, 2, 4, 6 per page)
Print Optimizations
Section titled “Print Optimizations”- Gradients rendered as static (deterministic output)
- Animations frozen at default state
- High resolution (2x scale)
- Embedded fonts
HTML Assembly
Section titled “HTML Assembly”Components
Section titled “Components”Each rendered page includes:
<!doctype html><html lang="..."> <head> <meta charset="utf-8" /> <style> /* Embedded fonts as base64 */ /* App CSS */ /* Theme variables */ /* Slide styles */ </style> </head> <body> <div class="ps-theme"> <!-- Slide HTML --> </div> <script>/* Prism/KaTeX init */</script> </body></html>CSS Handling
Section titled “CSS Handling”Stylesheets are:
- Inlined (no external requests)
- Font-faces embedded as data URLs
- Theme variables applied
- Imports resolved recursively
Image Handling
Section titled “Image Handling”Images are converted to data URLs:
// Local images become base64/uploads/image.jpg → data:image/jpeg;base64,...This ensures all resources are available during render.
Rendering API
Section titled “Rendering API”Internal Use
Section titled “Internal Use”The rendering system is used by:
- Export endpoints - PDF, PNG export
- Publish - OG image generation
- Thumbnails - Slide library previews
Endpoint Example
Section titled “Endpoint Example”POST /api/presentations/:id/slides/:slideId/renderContent-Type: application/json
{ "scale": 2, "format": "png"}
Response: PNG binaryPuppeteer Configuration
Section titled “Puppeteer Configuration”Environment Variables
Section titled “Environment Variables”# Path to Chromium binaryPUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
# Disable sandbox (Docker)PUPPETEER_NO_SANDBOX=trueDocker Setup
Section titled “Docker Setup”The Dockerfile includes Chromium:
RUN apk add --no-cache \ chromium \ nss \ freetype \ harfbuzz \ ca-certificates \ ttf-freefontBrowser Pool
Section titled “Browser Pool”A single browser instance is shared:
let browser = null;
async function getPuppeteerBrowser() { if (!browser) { browser = await puppeteer.launch({ executablePath: process.env.PUPPETEER_EXECUTABLE_PATH, headless: 'new', args: ['--no-sandbox', '--disable-setuid-sandbox'] }); } return browser;}Font Handling
Section titled “Font Handling”Embedded Fonts
Section titled “Embedded Fonts”Fonts are embedded for consistent rendering:
- Font files read from disk
- Converted to base64
- Injected as @font-face with data URLs
- Original @font-face rules stripped
Custom Theme Fonts
Section titled “Custom Theme Fonts”If a theme specifies custom fonts:
- Google Fonts are downloaded
- Local fonts are embedded
- Fallback fonts applied if unavailable
Special Cases
Section titled “Special Cases”Video Slides
Section titled “Video Slides”Video slides render a static preview:
- First frame or poster image
- Play button overlay
- Caption/title text
Interactive Slides
Section titled “Interactive Slides”Polls, Q&A, and other interactive elements:
- Render in default/empty state
- No live data included
- Placeholder text where appropriate
Follow Invite Slides
Section titled “Follow Invite Slides”These are skipped for OG images (first meaningful slide used instead).
Performance
Section titled “Performance”Caching
Section titled “Caching”- Browser instance reused
- Page created per render (cleaned up after)
- No result caching (renders are cheap)
Memory
Section titled “Memory”Each render temporarily uses:
- ~100-200MB for page
- Buffer size varies by scale
- Cleaned up after each render
Timeout
Section titled “Timeout”Default timeout: 30 seconds per render
Long renders may indicate:
- Large/complex slides
- Missing resources
- Network issues
Troubleshooting
Section titled “Troubleshooting”Blank Output
Section titled “Blank Output”- Check Chromium is installed
- Verify PUPPETEER_EXECUTABLE_PATH
- Check for JavaScript errors in console
Missing Fonts
Section titled “Missing Fonts”- Ensure fonts are accessible
- Check theme configuration
- Verify font embedding worked
Out of Memory
Section titled “Out of Memory”- Reduce scale factor
- Process fewer slides at once
- Increase container memory limits
Slow Rendering
Section titled “Slow Rendering”- Check image sizes
- Reduce complex animations
- Verify network for external resources