A WebGPU retro game engine for TypeScript, inspired by RetroBlit. Build pixel-perfect 2D games with a clean, fantasy-console-style API.
TypeScript 92%
JavaScript 6%
HTML 2%
Shell <1%

README.md

Blit-Tech #

CI npm version License: ISC WebGPU pnpm

A palette-first WebGPU retro engine for TypeScript, inspired by RetroBlit. Draw with palette indices, animate with palette cycling and fades, and ship authentic VGA-era effects on modern GPUs.

Blit-Tech logo

Inspiration #

Blit-Tech draws heavy inspiration from RetroBlit by Martin Cietwierkowski (@daafu) - a retro pixel demo framework for Unity that replaces the editor with a clean, low-level demo loop. Blit-Tech brings the same philosophy to the web using WebGPU: no scene graphs, no complex frameworks, just sprites, primitives, and fonts.

Features #

  • True indexed rendering: primitives and sprites write palette indices, not RGBA pixels
  • Palette effects built-in: cycling, fade, flash, and swap run per frame with no per-sprite rewrites
  • Built-in retro palettes: VGA, CGA, C64, Game Boy, PICO-8, and NES preset factories
  • Palette offset variants: recolor one sprite sheet into team colors, states, or themes without duplicate textures
  • Performance-first data model: tiny palette uploads (4 KB), smaller sprite textures, and compact primitive vertices
  • WebGPU rendering with dual-pipeline architecture (primitives + sprites); automatic Canvas 2D software fallback
  • Post-process effects: two-tier system - pixel tier on the r8uint index framebuffer; display tier on upscaled RGBA; bundled CRT presets
  • Primitive drawing: pixels, lines, rectangles (outline and filled)
  • Sprite system: palette-indexed textures, palette offset, automatic texture batching
  • Bitmap fonts: variable-width rendering from .btfont files with palette offset support
  • Camera system: scrolling with offset/reset and world-bounds clamping via BT.cameraClamp
  • Asset loading: sprite sheets and bitmap fonts with automatic caching
  • Pointer input: mouse, touch, and pen unified under four slots; scroll delta; cursor control
  • Keyboard input: raw keys via KeyboardEvent.code, virtual face buttons, remapping, text accumulation
  • Gamepad input: up to four players via standard Gamepad API, stick dead zone, face buttons
  • Fixed timestep: deterministic update loop with tick counter, Timer, and timing helpers
  • Frame capture: BT.captureFrame() and BT.downloadFrame() for PNG export

Why Blit-Tech? #

Feature Blit-Tech Typical 2D WebGPU engines
Rendering model Native indexed palette pipeline RGBA textures and framebuffers
Color animation Palette cycling/fade/flash built-in Manual sprite or shader rewrites
Global recolor/fade cost One palette update Scene redraw and blend passes
Color variants Palette offsets Duplicate assets or tint logic
Retro palette presets C64, NES, Game Boy, CGA, VGA, etc. Usually custom/manual only

Prerequisites #

Runtime (browser)

  • A WebGPU-compatible browser (the engine falls back to Canvas 2D software rendering when WebGPU is unavailable):
    • Chrome/Edge 113+ (Windows, macOS, Linux, Android)
    • Firefox 141+ on Windows; 145+/147+ on macOS; Nightly on Linux and Android
    • Safari 26+ (macOS Tahoe / iOS 26); or Safari 18-25 with WebGPU enabled via Feature Flags

App toolchain

  • Node.js >=22.18.0 (LTS)
  • An ESM bundler (Vite, webpack, esbuild, and similar) to load the published package in the browser

Installation #

Install blit-tech from npm:

pnpm add blit-tech

Or with npm:

npm install blit-tech

Package page: npmjs.com/package/blit-tech

Examples & Demos #

For interactive examples and demos, visit the Blit-Tech Demos repository.

Quick Start #

bootstrap() expects a canvas inside #canvas-container (defaults: canvas id blit-tech-canvas, container id canvas-container). Pair the HTML below with a TypeScript entry module in any ESM bundler setup.

index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My Blit-Tech Demo</title>
  </head>
  <body>
    <div id="canvas-container"><canvas id="blit-tech-canvas"></canvas></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

src/main.ts

import { bootstrap, BT, Color32, Palette, Rect2i, type IBlitTechDemo } from 'blit-tech';

const BG = 1;
const WATER_A = 9;
const WATER_B = 12;

class MyDemo implements IBlitTechDemo {
  async init(): Promise<boolean> {
    const palette = Palette.c64();
    palette.set(BG, new Color32(20, 30, 40, 255));
    BT.paletteSet(palette);

    // Animate every pixel that uses slots 9..12 (water/lava style cycling).
    BT.paletteCycle(WATER_A, WATER_B, 6);

    // Quick full-screen impact flash via palette manipulation.
    BT.paletteFlash(Color32.white, 120);

    return true;
  }

  update(): void {
    // fixed-step logic here
  }

  render(): void {
    BT.clear(BG);
    BT.drawRectFill(new Rect2i(100, 100, 50, 50), WATER_A);
  }
}

bootstrap(MyDemo);

Scaffold and run (Vite + TypeScript):

pnpm create vite my-demo --template vanilla-ts
cd my-demo
pnpm add blit-tech
# Add the HTML and main.ts snippets above, then:
pnpm dev

Documentation #

See API: Core for bootstrap() options.

Guide What it covers
API: Core bootstrap, game loop, camera, Timer, core types
API: Rendering primitives, sprites, text, post-process, frame capture
API: Palette palette setup, presets, effects, serialization
API: Assets sprite sheets, bitmap fonts, asset loading
Input Guide pointer, keyboard, gamepad
Palette Guide palette-first workflow, offsets, effects
Palette Presets built-in preset reference and exact color data
Post-Process Effects effect chain, built-in effects, custom effects
Bitmap Fonts .btfont format and BMFont conversion

Browser Compatibility #

WebGPU support varies by browser:

Browser Version Status
Chrome/Edge 113+ Enabled by default
Firefox 141+ (Windows) Enabled by default; 145+/147+ on macOS; Nightly on Linux/Android
Safari 26+ Enabled by default; Safari 18-25 available via Feature Flags

When WebGPU is unavailable the engine falls back to the Canvas 2D software renderer automatically. A dismissible in-canvas "SOFTWARE RENDERER" banner appears to confirm the fallback is active. Use BT.activeBackend to detect which backend is running at runtime.

Contributors #

Contributor workflow, scripts, release process, and repository tooling docs live in Developer Experience and CONTRIBUTING.md.

License #

ISC