localhost:4200 says
X Error: Could not find Chrome (ver. 148.0.7778.97). This can occur if either
1. you did not perform an installation before running the script (e.g. `npx puppeteer browsers install chrome') or
2. your cache path is incorrectly configured (which is: /opt/
render/.cache/puppeteer).
For (2), check out our guide on configuring puppeteer at https:// pptr.dev/guides/configuration.
OK

here code server.js
* ═══════════════════════════════════════════
PDF ENGINE
═══════════════════════════════════════════ */
/**
* Opens the dashboard URL in a headless browser, waits for it to fully
* render, then exports it as an A4 PDF to `storage/reports/`.
*
* @param {string} url - Full URL Puppeteer should visit
* @param {string} token - JWT stored in localStorage so the page authenticates
* @param {string} fileName - Output filename (no path, just "Report_xxx.pdf")
* @returns {Promise} - Resolves with fileName on success
*/
async function generateDashboardPDF(url, token, fileName) {
// const browser = await puppeteer.launch({
// headless: 'new',
// args: [
// '--no-sandbox',
// '--disable-setuid-sandbox',
// '--disable-dev-shm-usage', // prevents crashes on low-memory VMs
// '--disable-gpu',
// ],
// });
const browser = await puppeteer.launch({
headless: 'new',
// Windows path – change to match your actual Chrome install
executablePath: process.env.CHROME_PATH ||
'C:\\Users\\admin\\.cache\\puppeteer\\chrome\\win64-148.0.7778.167\\chrome-win64\\chrome.exe',
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-gpu',
],
});
const page = await browser.newPage();
try {
const origin = new URL(url).origin;
// 1. Land on the origin first so we can write localStorage
await page.goto(origin, { waitUntil: 'domcontentloaded', timeout: 60_000 });
await page.evaluate(t => localStorage.setItem('token', t), token);
// 2. Navigate to the real report page
await page.setViewport({ width: 1400, height: 1800 });
await page.goto(url, { waitUntil: 'networkidle2', timeout: 90_000 });
// 3. Strip UI chrome that should not appear in the PDF
await page.addStyleTag({
content: `
.report-toolbar,
.btn-primary,
.mat-icon,
.btn-whatsapp,
input,
button { display: none !important; }
#pdf-root {
box-shadow: none !important;
margin: 0 !important;
width: 100% !important;
border: none !important;
}
body {
background: white !important;
overflow: hidden !important;
}
`,
});
// 4. Wait for Angular to finish rendering
await page.waitForSelector('#pdf-root', { timeout: 30_000 });
await new Promise(r => setTimeout(r, 5_000)); // allow charts/animations to settle
// 5. Write PDF
const pdfPath = path.join(reportsDir, fileName);
await page.pdf({
path: pdfPath,
format: 'A4',
printBackground: true,
margin: { top: '10mm', right: '10mm', bottom: '10mm', left: '10mm' },
});
// 6. Sanity-check: reject obviously empty files
const { size } = fs.statSync(pdfPath);
if (size < 5_000) {
throw new Error(`Generated PDF is suspiciously small (${size} bytes). The page may not have rendered correctly.`);
}
console.log(`✅ PDF created: ${fileName} (${(size / 1024).toFixed(1)} KB)`);
return fileName;
} finally {
await browser.close();
}
}