fuzzyworld

when-am-i / files / scripts / screenshot-readme.mts

screenshot-readme.mts

Blame: the commit that last changed each line · file · history

76ecf55e 2026-06-21 Pavel Safronov1// Generate the two screenshots embedded in the README.
2//
3// Unlike generate-screenshots.mts (full-page app-state captures for internal
4// review) these are deliberately small and cropped — a README hero image
5// should read at a glance, not reproduce the whole page. The landing shot is
6// the full viewport (narrow, so the header/intro/map fit together); the
7// example shot clips to just the map+answers column (`.app-cols`), skipping
8// the header and intro text since by then the reader already has context.
9//
10// npm run screenshot:readme
11//
12// Output: screenshots/readme/*.png — committed, embedded via README.md.
13
14import { chromium } from 'playwright';
15import { mkdir, rm } from 'node:fs/promises';
16import path from 'node:path';
17import { startDevServer, BASE_URL, REPO_ROOT } from './lib/server.mts';
18
19const OUT_DIR = path.join(REPO_ROOT, 'screenshots', 'readme');
20const VIEWPORT = { width: 1000, height: 700 };
21
22async function run() {
23 console.log('\n📸 Generating README screenshots…\n');
24 const server = await startDevServer();
25 try {
26 await rm(OUT_DIR, { recursive: true, force: true });
27 await mkdir(OUT_DIR, { recursive: true });
28
29 const browser = await chromium.launch();
30 const page = await browser.newPage({ viewport: VIEWPORT, deviceScaleFactor: 2 });
31
32 // 1. Landing: no pin yet, today's date — the first thing a visitor sees.
33 await page.goto(BASE_URL, { waitUntil: 'networkidle' });
34 await page.waitForTimeout(500);
35 await page.screenshot({ path: path.join(OUT_DIR, '01-landing.png') });
36 console.log(' ✅ 01-landing.png');
37
38 // 2. Example: Boston, 1650 — two coexisting calendars (Massachusett +
39 // colonial Julian), cropped to the map+answers column only.
40 await page.goto(`${BASE_URL}?lat=42.32&lng=-71.06&zoom=10&year=1650&month=6&day=15`, {
41 waitUntil: 'networkidle',
42 });
43 await page.waitForTimeout(800); // let map tiles settle
44 await page.locator('.app-cols').screenshot({ path: path.join(OUT_DIR, '02-example.png') });
45 console.log(' ✅ 02-example.png');
46
47 await browser.close();
48 console.log('\n✨ Done — screenshots/readme/\n');
49 } finally {
50 server.stop();
51 }
52}
53
54run().catch((err) => {
55 console.error(err);
56 process.exit(1);
57});