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.)
ℹ️ Note

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.

bash
npm install @1990-archive/renderer-core
# or with yarn
yarn add @1990-archive/renderer-core

For Docker deployment:

bash
docker run -p 8080:8080 1990archive/renderer:2.4.0

Quick Start

Initialize the engine and render a historical URL:

javascript
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`);
💡 Pro Tip

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.

OptionTypeDefaultDescription
targetBrowserstring'netscape-3.0'Browser emulation profile
resolutionstring'1024x768'Viewport dimensions
colorDepthnumber8Bits per pixel (8 or 16)
enableMIDIbooleantrueEnable background MIDI simulation
strictModebooleanfalseThrow 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: 19901999.

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.

javascript
// .env or config file
RENDERER_CACHE_DIR=./.cache/archive_v2
RENDERER_WORKER_THREADS=4
RENDERER_ASSET_TIMEOUT=30000
RENDERER_STRICT_CSS_PARSING=false
⚠️ Warning

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: true is set. The engine will substitute missing GIFs/JPGs with era-accurate placeholders.
  • Frameset infinite loops: Set maxFrameDepth: 5 in options. Legacy frames often referenced themselves recursively.
  • Font rendering mismatch: Install corefonts-truetype or use the bundled ms-sans-serif-1996 subset.
  • High memory usage: Enable gcInterval: 2000 to 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.