import puppeteer from 'puppeteer' import type { Browser } from 'puppeteer' export default defineEventHandler(async (event) => { let browser: Browser | null = null try { const requestUrl = getRequestURL(event) const host = requestUrl.host.includes('192.168') || requestUrl.host.includes('localhost') ? 'localhost:5000' : requestUrl.host const baseUrl = `http://${host}` const resumeUrl = `${baseUrl}/resume?print=true` console.log('[PDF API] Generating from:', resumeUrl) const isDev = process.env.NODE_ENV === 'development' if (isDev) { browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'], }) } else { const chromium = await import('@sparticuz/chromium') const puppeteerCore = await import('puppeteer-core') browser = await puppeteerCore.default.launch({ args: chromium.default.args, executablePath: await chromium.default.executablePath(), headless: true, }) } const page = await browser.newPage() // Set viewport to A4 dimensions (210mm x 297mm at 96 DPI) await page.setViewport({ width: 794, // 210mm height: 1123 // 297mm }) // Enable print media type BEFORE loading page await page.emulateMediaType('print') const response = await page.goto(resumeUrl, { waitUntil: 'networkidle0', timeout: 30000, }) if (!response || !response.ok()) { throw new Error(`Failed to load: ${response?.status()}`) } // Inject critical CSS fixes await page.addStyleTag({ content: ` @page { size: A4; margin: 1.2cm; } * { box-shadow: none !important; word-break: normal !important; hyphens: none !important; -webkit-hyphens: none !important; -ms-hyphens: none !important; } html, body { margin: 0 !important; padding: 0 !important; background: white !important; min-height: auto !important; } .resume-wrapper { background: white !important; padding: 0 !important; display: block !important; margin: 0 !important; } .resume-container { box-shadow: none !important; max-width: none !important; width: 100% !important; margin: 0 !important; padding: 0 !important; } .resume-content { padding: 0 !important; } section { page-break-inside: auto !important; break-inside: auto !important; } h2 { page-break-after: avoid !important; break-after: avoid !important; } `, }) const pdf = await page.pdf({ format: 'A4', printBackground: true, margin: { top: 0, right: 0, bottom: 0, left: 0 }, preferCSSPageSize: true, }) const query = getQuery(event) const filename = (query.filename as string) || 'Ali_Arghyani_Resume.pdf' const download = query.download === 'true' setResponseHeaders(event, { 'Content-Type': 'application/pdf', // inline = show in browser, attachment = force download 'Content-Disposition': `${download ? 'attachment' : 'inline'}; filename="${filename}"`, }) return pdf } catch (error) { console.error('PDF generation failed:', error) setResponseStatus(event, 500) return { error: 'PDF generation failed', message: error instanceof Error ? error.message : 'Unknown error', } } finally { if (browser) { await browser.close() } } })