feat: conversion landing page with automated screenshots
This commit is contained in:
parent
85c5a8381c
commit
82f7ff8b02
8 changed files with 362 additions and 35 deletions
66
frontend/scripts/capture.mjs
Normal file
66
frontend/scripts/capture.mjs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/* Repeatable landing-page screenshots (re-run after UI changes).
|
||||
*
|
||||
* Usage (frontend container, dev server running):
|
||||
* npm run screenshots # light scheme (default)
|
||||
* npm run screenshots -- --scheme=dark
|
||||
*
|
||||
* Captures real app states into public/screenshots/ (committed, so the
|
||||
* landing page always shows current UI). Authenticated states are out of
|
||||
* scope (magic-link login is not scriptable without SMTP).
|
||||
*/
|
||||
|
||||
import { mkdirSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { chromium } from "playwright";
|
||||
|
||||
const root = join(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const outDir = join(root, "public", "screenshots");
|
||||
const base = process.env.SCREENSHOT_BASE_URL ?? "http://localhost:3000";
|
||||
const schemeArg = process.argv.find((a) => a.startsWith("--scheme="));
|
||||
const scheme = schemeArg ? schemeArg.split("=")[1] : "light";
|
||||
|
||||
const shots = [
|
||||
{ name: "hero", path: "/", fullPage: true },
|
||||
{
|
||||
name: "workflows",
|
||||
path: "/app/workflows",
|
||||
fullPage: false,
|
||||
selectFlow: "intake_form",
|
||||
},
|
||||
];
|
||||
|
||||
const browser = await chromium.launch();
|
||||
try {
|
||||
mkdirSync(outDir, { recursive: true });
|
||||
const context = await browser.newContext({
|
||||
viewport: { width: 1440, height: 900 },
|
||||
colorScheme: scheme === "dark" ? "dark" : "light",
|
||||
});
|
||||
await context.addInitScript(
|
||||
(value) => {
|
||||
try {
|
||||
localStorage.setItem("kirche-color-scheme", value);
|
||||
} catch {
|
||||
/* private mode */
|
||||
}
|
||||
},
|
||||
scheme === "dark" ? "dark" : "light",
|
||||
);
|
||||
const page = await context.newPage();
|
||||
for (const shot of shots) {
|
||||
await page.goto(base + shot.path, { waitUntil: "networkidle" });
|
||||
await page.waitForTimeout(1500);
|
||||
if (shot.selectFlow) {
|
||||
// Show the generated RJSF form instead of the default first flow.
|
||||
await page.locator('[role="combobox"]').first().click();
|
||||
await page.getByRole("option", { name: shot.selectFlow }).click();
|
||||
await page.waitForTimeout(2000);
|
||||
}
|
||||
const file = join(outDir, `${shot.name}-${scheme}.png`);
|
||||
await page.screenshot({ path: file, fullPage: shot.fullPage });
|
||||
console.log(`wrote ${file}`);
|
||||
}
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue