Rendering Engine v2.4.0
A high-fidelity engine for emulating 1990–1999 browser rendering behavior. Supports Netscape Navigator, IE4, Mosaic, and early Opera with pixel-accurate layout simulation.
Overview
The 1990 Web Archive Rendering Engine is a standalone module that reconstructs historical web pages exactly as they were rendered on period-correct hardware. Unlike modern emulators, this engine operates at the CSSOM and layout tree level, applying era-specific constraints:
- Table-based layout simulation (no flexbox/grid fallback)
- CSS1 / Early CSS2 property parsing with known quirks
- Fixed 256-color palette mapping (8-bit depth default)
- Native frame and frameset reconstruction
- Legacy HTML tag support (
<font>,<center>,<marquee>, etc.)
Version 2.4+ introduces WebGL-accelerated rasterization for 1440x900 and higher resolutions while maintaining authentic color quantization and anti-aliasing behavior.
Installation
The engine is distributed as an npm package. Node.js 18+ or modern browsers (ESM compatible) are required.
npm install @1990-archive/renderer-core
# or with yarn
yarn add @1990-archive/renderer-core
For Docker deployment:
docker run -p 8080:8080 1990archive/renderer:2.4.0
Quick Start
Initialize the engine and render a historical URL:
import { Renderer } from '@1990-archive/renderer-core';
const engine = await Renderer.init({
targetBrowser: 'netscape-3.0',
resolution: '800x600',
colorDepth: 8
});
const page = await engine.loadURL('http://www.geocities.com/~coolpage');
// Export as PNG or interactive DOM snapshot
await page.exportSnapshot('/output/1997-homepage.png');
console.log(`Rendered ${page.meta.title} in ${page.meta.renderTime}ms`);
Use strictMode: false to allow graceful degradation for malformed HTML common in the mid-90s. The engine will auto-recover broken table structures and unclosed tags.
API Reference
Renderer.init(options)
Bootstraps the rendering context. Returns a promise resolving to the engine instance.
| Option | Type | Default | Description |
|---|---|---|---|
targetBrowser | string | 'netscape-3.0' | Browser emulation profile |
resolution | string | '1024x768' | Viewport dimensions |
colorDepth | number | 8 | Bits per pixel (8 or 16) |
enableMIDI | boolean | true | Enable background MIDI simulation |
strictMode | boolean | false | Throw on invalid HTML4/CSS1 |
engine.loadURL(url, opts?)
Fetches and parses a URL through the era-appropriate parser chain. Supports local paths, archived WARCs, and live HTTP(S) with proxy fallback.
page.setEra(year)
Dynamic era switching. Adjusts font metrics, color profiles, and layout heuristics to match the specified year. Valid range: 1990–1999.
page.exportSnapshot(path, format?)
Renders the final composited frame to disk. Supports png, webp, and raw-dom formats.
Configuration
Advanced tuning is available via environment variables or runtime config objects. The engine caches parsed stylesheets and layout trees for repeat renders.
// .env or config file
RENDERER_CACHE_DIR=./.cache/archive_v2
RENDERER_WORKER_THREADS=4
RENDERER_ASSET_TIMEOUT=30000
RENDERER_STRICT_CSS_PARSING=false
Increasing WORKER_THREADS beyond 6 on single-tenant servers may cause memory fragmentation during batch processing of GeoCities dumps.
Troubleshooting
- Broken image tiles: Ensure
assetFallback: trueis set. The engine will substitute missing GIFs/JPGs with era-accurate placeholders. - Frameset infinite loops: Set
maxFrameDepth: 5in options. Legacy frames often referenced themselves recursively. - Font rendering mismatch: Install
corefonts-truetypeor use the bundledms-sans-serif-1996subset. - High memory usage: Enable
gcInterval: 2000to force garbage collection between page renders.
FAQ
Can I render JavaScript-heavy sites?
Early web JS (LiveScript, IE4 DHTML) is supported via our retro-VM sandbox. Modern ES6+ syntax will be stripped or transpiled to 1998-compatible syntax automatically.
Is this engine suitable for production scraping?
Yes, but we recommend using the headless Docker image with rate-limiting enabled. The engine is optimized for archival accuracy, not speed.
How do I contribute browser profiles?
Submit CSS/HTML quirk definitions via our GitHub repository. All profiles undergo historical validation before merging.