/** * Post-build pre-renderer for sase.tr public pages. * * Starts a local vite preview server, visits each public route with * headless Chromium, and saves the fully-rendered HTML to dist/. * Crawlers that don't execute JavaScript receive complete HTML. * * Usage: node scripts/prerender.mjs * Requires: dist/ to already exist (run `vite build` first) */ import { chromium } from "playwright"; import { preview } from "vite"; import { writeFileSync, mkdirSync, existsSync } from "fs"; import { join, dirname } from "path"; import { fileURLToPath } from "url"; const __dirname = dirname(fileURLToPath(import.meta.url)); const ROOT = join(__dirname, ".."); const DIST = join(ROOT, "dist"); const PORT = 4174; /** Public routes to pre-render. Dashboard/auth routes are excluded — they require login. */ const ROUTES = [ "/", "/pricing", "/about", "/blog", "/blog/vin-nedir-nasil-okunur", "/blog/orijinal-mi-muadil-mi", "/blog/dijital-donusum", "/blog/dogru-parcayi-bulun", "/contact", "/demo", ]; async function prerender() { if (!existsSync(DIST)) { console.error("āŒ dist/ not found — run `vite build` first."); process.exit(1); } console.log("šŸ” Starting pre-render...\n"); // Start vite preview server (serves from dist/) const server = await preview({ root: ROOT, preview: { port: PORT, strictPort: false }, logLevel: "silent", }); const browser = await chromium.launch({ args: ["--no-sandbox"] }); try { for (const route of ROUTES) { const page = await browser.newPage(); // Block all /api/ requests so auth resolves to unauthenticated immediately. // Without this the page hangs waiting for session checks. await page.route("**/api/**", (r) => r.fulfill({ status: 401, contentType: "application/json", body: JSON.stringify({ success: false, error: { code: "UNAUTHORIZED" } }), }), ); await page.goto(`http://localhost:${PORT}${route}`, { waitUntil: "networkidle", timeout: 30_000, }); // Extra settle time for any deferred renders (animations, etc.) await page.waitForTimeout(300); const html = await page.content(); if (route === "/") { writeFileSync(join(DIST, "index.html"), html, "utf-8"); } else { const dir = join(DIST, route); mkdirSync(dir, { recursive: true }); writeFileSync(join(dir, "index.html"), html, "utf-8"); } await page.close(); console.log(` āœ“ ${route}`); } } finally { await browser.close(); await server.close(); } console.log("\nāœ… Pre-render complete — all routes saved to dist/\n"); } prerender().catch((err) => { console.error("āŒ Pre-render failed:", err.message); process.exit(1); });