gallery / scripts /screenshot-templates.js
Hanzo Dev
feat: Add screenshot tool and update dependencies
2e17c87
#!/usr/bin/env node
/**
* Screenshot Tool for Hanzo Template Gallery
* Captures screenshots of all templates programmatically
* Usage: node scripts/screenshot-templates.js
*/
const puppeteer = require('puppeteer');
const fs = require('fs').promises;
const path = require('path');
// Import template data directly
const templateData = require('../components/template-data');
const templates = templateData.templates || [];
const SCREENSHOT_DIR = path.join(process.cwd(), 'public', 'screenshots');
const BASE_URL = process.env.SCREENSHOT_BASE_URL || 'http://localhost:3000';
async function ensureDir(dir) {
try {
await fs.mkdir(dir, { recursive: true });
} catch (err) {
console.error(`Error creating directory ${dir}:`, err);
}
}
async function captureTemplateScreenshot(browser, template) {
const page = await browser.newPage();
// Set dark mode preference
await page.emulateMediaFeatures([
{ name: 'prefers-color-scheme', value: 'dark' }
]);
// Set viewport for consistent screenshots
await page.setViewport({
width: 1920,
height: 1080,
deviceScaleFactor: 2, // Higher quality screenshots
});
try {
const templateUrl = template.demoUrl || `${BASE_URL}/template/${template.id}`;
console.log(`πŸ“Έ Capturing screenshot for ${template.name}...`);
// Navigate to template page
await page.goto(templateUrl, {
waitUntil: ['networkidle0', 'domcontentloaded'],
timeout: 30000,
});
// Wait a bit for animations to complete
await page.waitForTimeout(2000);
// Capture full page screenshot
const screenshotPath = path.join(SCREENSHOT_DIR, `${template.id}.png`);
await page.screenshot({
path: screenshotPath,
fullPage: false, // Just viewport for consistency
});
// Also capture a thumbnail version
await page.setViewport({
width: 800,
height: 600,
deviceScaleFactor: 2,
});
const thumbnailPath = path.join(SCREENSHOT_DIR, `${template.id}-thumb.png`);
await page.screenshot({
path: thumbnailPath,
fullPage: false,
});
// Capture mobile version
await page.setViewport({
width: 375,
height: 812,
deviceScaleFactor: 2,
isMobile: true,
hasTouch: true,
});
const mobilePath = path.join(SCREENSHOT_DIR, `${template.id}-mobile.png`);
await page.screenshot({
path: mobilePath,
fullPage: false,
});
console.log(`βœ… Saved screenshots for ${template.name}`);
return {
success: true,
template: template.name,
screenshots: {
desktop: `${template.id}.png`,
thumbnail: `${template.id}-thumb.png`,
mobile: `${template.id}-mobile.png`,
}
};
} catch (error) {
console.error(`❌ Error capturing ${template.name}:`, error.message);
return {
success: false,
template: template.name,
error: error.message,
};
} finally {
await page.close();
}
}
async function captureGalleryScreenshot(browser) {
const page = await browser.newPage();
// Set dark mode
await page.emulateMediaFeatures([
{ name: 'prefers-color-scheme', value: 'dark' }
]);
await page.setViewport({
width: 1920,
height: 1080,
deviceScaleFactor: 2,
});
try {
console.log(`πŸ“Έ Capturing gallery homepage...`);
await page.goto(BASE_URL, {
waitUntil: ['networkidle0', 'domcontentloaded'],
timeout: 30000,
});
await page.waitForTimeout(2000);
// Capture hero section
const heroPath = path.join(SCREENSHOT_DIR, 'gallery-hero.png');
await page.screenshot({
path: heroPath,
fullPage: false,
});
// Scroll to templates section and capture
await page.evaluate(() => {
window.scrollBy(0, window.innerHeight);
});
await page.waitForTimeout(1000);
const templatesPath = path.join(SCREENSHOT_DIR, 'gallery-templates.png');
await page.screenshot({
path: templatesPath,
fullPage: false,
});
// Capture full page
await page.evaluate(() => {
window.scrollTo(0, 0);
});
await page.waitForTimeout(500);
const fullPagePath = path.join(SCREENSHOT_DIR, 'gallery-full.png');
await page.screenshot({
path: fullPagePath,
fullPage: true,
});
console.log(`βœ… Saved gallery screenshots`);
return { success: true };
} catch (error) {
console.error(`❌ Error capturing gallery:`, error.message);
return { success: false, error: error.message };
} finally {
await page.close();
}
}
async function main() {
console.log('πŸš€ Starting Hanzo Template Gallery Screenshot Tool');
console.log(`πŸ“ Screenshots will be saved to: ${SCREENSHOT_DIR}`);
console.log(`🌐 Base URL: ${BASE_URL}`);
console.log(`πŸ“ Found ${templates.length} templates to capture`);
console.log('');
// Ensure screenshot directory exists
await ensureDir(SCREENSHOT_DIR);
// Launch browser
const browser = await puppeteer.launch({
headless: 'new',
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--no-first-run',
'--no-zygote',
'--disable-gpu',
],
});
try {
const results = [];
// Capture gallery homepage
const galleryResult = await captureGalleryScreenshot(browser);
results.push(galleryResult);
// Capture each template
for (const template of templates) {
const result = await captureTemplateScreenshot(browser, template);
results.push(result);
// Small delay between captures
await new Promise(resolve => setTimeout(resolve, 1000));
}
// Generate summary
console.log('\nπŸ“Š Screenshot Capture Summary:');
console.log('================================');
const successful = results.filter(r => r.success).length;
const failed = results.filter(r => !r.success).length;
console.log(`βœ… Successful: ${successful}`);
console.log(`❌ Failed: ${failed}`);
if (failed > 0) {
console.log('\nFailed captures:');
results
.filter(r => !r.success)
.forEach(r => console.log(` - ${r.template}: ${r.error}`));
}
// Save metadata
const metadata = {
capturedAt: new Date().toISOString(),
baseUrl: BASE_URL,
totalTemplates: templates.length,
captureResults: results.map(r => ({
name: r.template || 'Gallery',
success: r.success,
screenshots: r.screenshots,
error: r.error,
})),
};
const metadataPath = path.join(SCREENSHOT_DIR, 'metadata.json');
await fs.writeFile(metadataPath, JSON.stringify(metadata, null, 2));
console.log(`\nπŸ’Ύ Metadata saved to ${metadataPath}`);
} catch (error) {
console.error('Fatal error:', error);
process.exit(1);
} finally {
await browser.close();
}
}
// Run if called directly
if (require.main === module) {
main().catch(console.error);
}
module.exports = { captureTemplateScreenshot, captureGalleryScreenshot };