The site now exists in German (at the root, with /impressum and /datenschutz) and English (/en). A request without a language follows the visitor's choice from the language switch, then the browser language, then German; the old English legal addresses move to /en for good. All visible texts are data in src/content/de.ts and en.ts, so components hold none of their own. The header carries a DE/EN switch whose bit curtain covers the page while it is swapped and reopens at the same reading position. Title, description, canonical, hreflang, Open Graph, the share image, the sitemap and the structured data are per language. The privacy notice now describes the cookie that remembers the chosen language. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
68 lines
3.1 KiB
JavaScript
68 lines
3.1 KiB
JavaScript
// Renders the share images (Open Graph and Twitter) from the real hero, one per
|
|
// language, so they always match the site. Run it after the hero headline or its
|
|
// design changes:
|
|
//
|
|
// pnpm --filter @mintel/web share-image (uses the live site)
|
|
// pnpm --filter @mintel/web share-image http://localhost:3000
|
|
//
|
|
// It drives the locally installed Chrome through Playwright and writes
|
|
// src/assets/share/share-de.png and share-en.png (used by app/[locale]/layout.tsx).
|
|
import { chromium } from "playwright";
|
|
|
|
const origin = (process.argv[2] ?? "https://mintel.me").replace(/\/$/, "");
|
|
// The browser language matches the page, so the language detection lets it through.
|
|
const SHOTS = [
|
|
{ locale: "de", path: "/", browserLocale: "de-DE" },
|
|
{ locale: "en", path: "/en", browserLocale: "en-US" },
|
|
];
|
|
const browser = await chromium.launch({ channel: "chrome", headless: true });
|
|
for (const shot of SHOTS) {
|
|
const out = `src/assets/share/share-${shot.locale}.png`;
|
|
const page = await browser.newPage({
|
|
viewport: { width: 1200, height: 630 },
|
|
deviceScaleFactor: 1,
|
|
locale: shot.browserLocale,
|
|
});
|
|
await page.goto(`${origin}${shot.path}`, {
|
|
waitUntil: "load",
|
|
timeout: 90000,
|
|
});
|
|
await page.addStyleTag({
|
|
content: `
|
|
header, footer, #hero-cta, [class*="fixed"], nextjs-portal { display: none !important; }
|
|
main > div > section:first-of-type > div.relative { min-height: 630px !important; height: 630px !important; padding: 0 72px !important; justify-content: center !important; max-width: none !important; }
|
|
main > div > section:first-of-type ul { display: none !important; }
|
|
main > div > section:first-of-type h1 { font-size: 150px !important; }
|
|
main > div > section:first-of-type p { font-size: 34px !important; max-width: 900px !important; margin-top: 36px !important; }
|
|
main > div > section:first-of-type .grid { margin-top: 0 !important; display: block !important; }
|
|
main > div > section:first-of-type h1 span:nth-of-type(2) { color: rgba(15, 23, 42, 0.2) !important; }
|
|
main > div > section:first-of-type > div.relative { padding-top: 34px !important; }
|
|
html, body { overflow: hidden !important; }
|
|
`,
|
|
});
|
|
// Let the page finish starting up first; it would discard the added labels.
|
|
await page.waitForTimeout(2000);
|
|
await page.evaluate(() => {
|
|
const section = document.querySelector("main section");
|
|
const tag = document.createElement("div");
|
|
tag.textContent = "MARC MINTEL";
|
|
tag.style.cssText =
|
|
"position:absolute;left:72px;top:54px;z-index:20;font:700 15px ui-monospace,Menlo,monospace;letter-spacing:.3em;color:#0f172a";
|
|
const site = document.createElement("div");
|
|
site.textContent = "mintel.me";
|
|
site.style.cssText =
|
|
"position:absolute;right:72px;top:54px;z-index:20;font:500 15px ui-monospace,Menlo,monospace;letter-spacing:.2em;color:#64748b";
|
|
section.style.position = "relative";
|
|
section.append(tag, site);
|
|
window.scrollTo(0, 0);
|
|
});
|
|
await page.waitForTimeout(4500);
|
|
await page.screenshot({
|
|
path: out,
|
|
clip: { x: 0, y: 0, width: 1200, height: 630 },
|
|
});
|
|
await page.close();
|
|
console.log("written:", out);
|
|
}
|
|
await browser.close();
|