Export Workflow
Complete guide for exporting Aldea slide decks to PDF and static HTML.
Quick Reference
# Static HTML (shareable folder)
npm run export # Output: out/
# PDF (multi-page document)
npm run dev & # Start dev server first
npm run pdf # Output: output/[name]-YYYY-MM-DD.pdf
# Distribution package
zip -rq deck.zip out/ # Creates deck.zip
Static HTML Export
Build a static version that can be hosted anywhere or opened directly in browser.
Command
npm run export
Output
out/
├── index.html # Main page
├── _next/ # Next.js assets
│ ├── static/ # CSS, JS bundles
│ └── ...
└── images/ # Copied from public/images
Configuration (next.config.js)
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
output: 'export', // Enable static export
images: {
unoptimized: true, // Disable Next.js Image optimization
},
};
module.exports = nextConfig;
Hosting Options
Local viewing:
# Open directly in browser
open out/index.html
# Or serve with a local server
npx serve out
Vercel (recommended):
npm i -g vercel
vercel # Follow prompts
# Result: https://your-deck.vercel.app
Netlify:
# Drag-and-drop out/ folder to netlify.com
# Or use Netlify CLI:
npm i -g netlify-cli
netlify deploy --dir=out
GitHub Pages:
# Push out/ folder to gh-pages branch
# Or configure GitHub Actions
PDF Export
Generate a multi-page PDF using Puppeteer.
Prerequisites
- Dev server running — PDF script connects to localhost
- Puppeteer installed —
npm install puppeteer
Commands
# Terminal 1: Start dev server
npm run dev
# Terminal 2: Generate PDF
npm run pdf
Output
output/
└── aldea-journey-2026-01-06.pdf # Date-stamped PDF
Script (scripts/export-pdf.js)
const puppeteer = require('puppeteer');
const path = require('path');
const fs = require('fs');
async function exportToPDF() {
console.log('🚀 Starting PDF export...');
const browser = await puppeteer.launch({
headless: true,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-gpu'
]
});
const page = await browser.newPage();
// Set viewport to match slide dimensions (16:9)
await page.setViewport({
width: 1280,
height: 720,
deviceScaleFactor: 2
});
const url = process.env.URL || 'http://localhost:3200';
console.log(`📡 Connecting to ${url}...`);
try {
await page.goto(url, {
waitUntil: 'networkidle0',
timeout: 30000
});
} catch (error) {
console.error('❌ Failed to connect. Make sure the dev server is running:');
console.error(' npm run dev');
process.exit(1);
}
// Wait for fonts to load
await page.evaluateHandle('document.fonts.ready');
await new Promise(resolve => setTimeout(resolve, 2000));
// Inject print CSS to make each .slide a separate page
await page.addStyleTag({
content: `
@media print {
@page {
size: 1280px 720px;
margin: 0;
}
body {
margin: 0;
padding: 0;
}
.slide {
width: 1280px !important;
height: 720px !important;
page-break-after: always;
page-break-inside: avoid;
break-after: page;
break-inside: avoid;
}
.slide:last-child {
page-break-after: auto;
}
}
`
});
const slideCount = await page.evaluate(() => {
return document.querySelectorAll('.slide').length;
});
console.log(`📊 Found ${slideCount} slides`);
const outputDir = path.join(__dirname, '..', 'output');
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
const timestamp = new Date().toISOString().split('T')[0];
const outputPath = path.join(outputDir, `aldea-journey-${timestamp}.pdf`);
console.log('📄 Generating PDF...');
await page.pdf({
path: outputPath,
width: '1280px',
height: '720px',
printBackground: true,
preferCSSPageSize: true,
margin: { top: 0, right: 0, bottom: 0, left: 0 }
});
console.log(`\n✅ PDF exported to: ${outputPath}`);
await browser.close();
}
exportToPDF().catch(console.error);
Customization
Change output filename:
const outputPath = path.join(outputDir, `my-deck-${timestamp}.pdf`);
Change port:
URL=http://localhost:3000 npm run pdf
Increase wait time (for slow-loading content):
await new Promise(resolve => setTimeout(resolve, 5000)); // 5 seconds
Print CSS Requirements
Your slides must have the .slide class and proper print styles.
Slide Class
// In SlideLayout.tsx
<div className="slide relative ...">
{children}
</div>
Print Styles (globals.css)
@media print {
@page {
size: 1280px 720px;
margin: 0;
}
body {
margin: 0;
padding: 0;
}
.slide {
width: 1280px !important;
height: 720px !important;
page-break-after: always;
page-break-inside: avoid;
break-after: page;
break-inside: avoid;
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
}
.slide:last-child {
page-break-after: auto;
}
}
Color Preservation
The -webkit-print-color-adjust: exact and print-color-adjust: exact properties ensure backgrounds and colors are preserved in print/PDF output.
Distribution Package
Create a zip file for easy sharing.
Command
# Create zip from static export
zip -rq deck.zip out/
# Or include PDF
zip -rq deck-bundle.zip out/ output/*.pdf
Full Export Script
#!/bin/bash
# export-all.sh
echo "Building static export..."
npm run export
echo "Starting dev server..."
npm run dev &
DEV_PID=$!
sleep 5
echo "Generating PDF..."
npm run pdf
echo "Stopping dev server..."
kill $DEV_PID
echo "Creating zip..."
rm -f deck.zip
zip -rq deck.zip out/
echo "Done!"
ls -la deck.zip
Troubleshooting
PDF is empty
Cause: Dev server not running or wrong port.
Fix:
# Make sure dev server is running
npm run dev
# Check it's accessible
curl http://localhost:3200
All slides show the same content
Cause: Print CSS not properly set up.
Fix: Ensure .slide class is on each slide and print CSS includes page-break-after: always.
Colors look wrong in PDF
Cause: Print color adjustment not set.
Fix: Add to your CSS:
.slide {
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
}
Fonts not loading
Cause: Fonts not fully loaded before PDF generation.
Fix: Increase wait time in export-pdf.js:
await page.evaluateHandle('document.fonts.ready');
await new Promise(resolve => setTimeout(resolve, 3000)); // Increase to 3s
Static export fails
Cause: Dynamic routes or server-side features used.
Fix: Ensure all pages are static. Check next.config.js has:
output: 'export',
images: { unoptimized: true }
Slides overflow page boundaries
Cause: Content taller than 720px.
Fix:
- Use
flex-1for content areas to auto-fit - Reduce content or font sizes
- Use
overflow-hiddenon slide containers
Package.json Scripts
{
"scripts": {
"dev": "next dev -p 3200",
"build": "next build",
"export": "next build",
"pdf": "node scripts/export-pdf.js"
}
}
Checklist Before Export
- All slides render correctly at 1280×720
- Slide numbers are sequential
- Total slide count in SlideLayout is accurate
- Images are in public/images/
- Fonts are loaded (Google Fonts in _document.tsx)
- Print styles are in globals.css
- Dev server starts without errors