HTML snapshot / prerender via Playwright (Firefox).
C͗ͅr̬͕͉̩ͮeͧ̏͑̿d̊̚i͓̹̻͍ͮ̒̒ͭt̝̖͔̓͌͋ͪ\Ĩ͔̟͚̯͌ͦň̺̼̜͊s̉̅p͖̖̘ͫ̏̈́̚i͓̹̻͍ͮ̒̒ͭr̬͕͉̩ͮaͪ͊͆t̝̖͔̓͌͋ͪi͓̹̻͍ͮ̒̒ͭõ͍ň̺̼̜͊ (the original “tiny prerender” utility), but modernized around:
- Playwright (Firefox)
- npm-only workflow
- TS build output (ESM + CJS via
tsdown) - a demo runner that can capture assets + generate an offline “smoke” page
- run reports (
demo:report) for quick verification
Given a URL, it produces an HTML snapshot suitable for:
- quick SEO/prerender checks
- build-time content snapshots
- debugging hydration/client-render differences
- generating “offline-ish” smoke pages to validate what you captured
It is not a full recursive crawler. The “capture assets” mode captures responses seen during page load for a single page.
src/
browser.ts # singleton Firefox launcher (Playwright)
request.ts # main request() that returns HTML
utils.ts
examples/
demo.mjs # demo runner: cases + capture + smoke
report.mjs # generates report.html + report.json for latest run
clean.mjs # wipes .demo-out
test/
dist/ # build output
.demo-out/ # demo outputs (gitignored)
npm install
npm run demo:install # installs Playwright’s Firefox runtimenpm run build
npm testnpm run demo:cleancapture_assets_full is the main “offline verification” case.
npm run demo:minify-js -- --only capture_assets_full --goto domcontentloaded --gotoTimeout 120000 --wait 2500Notes:
--goto domcontentloadedavoids hanging onnetworkidle(modern sites often never go idle).--wait 2500gives the page time to load extra JS/CSS after initial navigation.
npm run demo:report$latest = Get-ChildItem .demo-out\runs | Sort-Object LastWriteTime -Descending | Select-Object -First 1
$report = Join-Path $latest.FullName "report.html"
ii $reportThe report includes:
- page link: raw snapshot HTML
- smoke link: locally-rewritten + inlined CSS/JS (when capture was enabled)
All demo flags are passed to examples/demo.mjs.
--url https://rosehillops.com/
--only capture_assets_full--skip manual_mode_injected
Comma-separated lists work:
--only capture_assets_full,components_slices
--goto domcontentloaded|load|networkidle--gotoTimeout 120000--wait 2500
--minify-js--chunk-js 20000
Outputs are written under each case:
assets/js/(captured raw)assets/js-min/(terser minified)assets/js-chunks/(minified split into readable chunks)
This repo uses debug namespace:
fuego:request
Option A: enable via demo flag:
npm run demo:debugOption B: enable manually (PowerShell):
$env:DEBUG="fuego:*"
npm run demoEach demo run is written to:
.demo-out/runs/<YYYYMMDD_HHMMSS>__<host>/
run.json
report.json
report.html
cases/
<case_name>/
manifest.json
html/page.html
assets/...
cdn/...
offline/smoke.html
components/...
Key files:
run.json– run-level metadata (target, args, timestamps)cases/<case>/manifest.json– per-case capture log (responses, failures, console, errors)report.json/report.html– summary view for the latest runoffline/smoke.html– browser verification page (CSS/JS inlined when captured)
import { request, cleanup } from 'fuego-firefox';
const html = await request({
url: 'https://rosehillops.com/',
minify: true,
});
await cleanup();Important options:
-
blockedResourceTypes?: string[]- Default blocks
stylesheet,image,media,font(fast snapshots) - Set to
[]to allow full capture workflows
- Default blocks
-
gotoWaitUntil?: "load" | "domcontentloaded" | "networkidle" -
gotoTimeoutMs?: number -
wait?: number | string(delay ms or wait-for-selector) -
manually?: boolean | string(manual snapshot mode)
npm run demo -- --only basicnpm run demo:clean
npm run demo:minify-js -- --only capture_assets_full --goto domcontentloaded --gotoTimeout 120000 --wait 2500
npm run demo:reportnpm run demo -- --only components_slices --goto domcontentloaded --gotoTimeout 120000