when-am-i / files / scripts / screenshot-readme.mts
screenshot-readme.mts
| 1 | // 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 | |
| 14 | import { chromium } from 'playwright'; |
| 15 | import { mkdir, rm } from 'node:fs/promises'; |
| 16 | import path from 'node:path'; |
| 17 | import { startDevServer, BASE_URL, REPO_ROOT } from './lib/server.mts'; |
| 18 | |
| 19 | const OUT_DIR = path.join(REPO_ROOT, 'screenshots', 'readme'); |
| 20 | const VIEWPORT = { width: 1000, height: 700 }; |
| 21 | |
| 22 | async 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 | |
| 54 | run().catch((err) => { |
| 55 | console.error(err); |
| 56 | process.exit(1); |
| 57 | }); |