← All articles
June 7, 2026Game

SpriteForge — A Browser-Based Sprite & Level Editor

Building a zero-dependency, fully static sprite editor and level generator that runs entirely in the browser.

canvasjavascriptgamedevtoolsstatic
Share

The Problem

Every 2D game project eventually hits the same wall: you need to create sprites and design levels, but you don't want to pull in a full editor suite like Tiled or Aseprite just to iterate quickly. SpriteForge is my answer — a lightweight, browser-based toolset that lives at demo.kmoussouni.dev/spriteforge.

What It Does

SpriteForge is a static web app (no backend, no build step) with two main tools:

Sprite Generator (sprite-generator.html) Draw and export pixel art sprites directly in the browser. The canvas-based editor supports per-pixel editing, palette management, and PNG export. No uploads, no accounts — everything runs client-side.

Level Generator (level-generator.html) Design tile-based levels visually and export them as JSON or code snippets ready to paste into a Phaser / canvas game. Supports multiple tile layers and collision masks.

A documentation page (doc.html) covers the keyboard shortcuts and export formats.

Architecture: Zero Dependencies

The entire toolset is vanilla JavaScript + HTML Canvas. No frameworks, no bundler, no node_modules. The reason is pragmatic: a static tool that loads in under 100ms and runs offline is more useful than a polished React app that takes 3 seconds to hydrate.

<!-- index.html — the whole thing -->
<canvas id="editor"></canvas>
<script src="editor.js"></script>

Deployment is trivial — drop the files anywhere. In production, it's served by Caddy as a static directory:

handle /spriteforge* {
    uri strip_prefix /spriteforge
    root * /srv/demos/spriteforge
    file_server
}

Canvas API Patterns

The pixel editor relies on ImageData for direct pixel manipulation — reading and writing individual RGBA values is far faster than drawing colored rectangles for each pixel.

const imageData = ctx.getImageData(0, 0, width, height)
const index = (y * width + x) * 4
imageData.data[index]     = r
imageData.data[index + 1] = g
imageData.data[index + 2] = b
imageData.data[index + 3] = 255
ctx.putImageData(imageData, 0, 0)

The zoom system scales the logical canvas (e.g. 16×16 pixels) to the display canvas via ctx.scale() + ctx.imageSmoothingEnabled = false — preserving crisp pixels at any zoom level.

Try It

The editor is live at demo.kmoussouni.dev/spriteforge — no install, no login.

Why Static?

Tools should be fast and self-contained. SpriteForge is used mid-development when you need to iterate quickly. A server round-trip for every export, or a 200KB framework boot, would break the flow. The static approach also means it works offline, can be self-hosted in 30 seconds, and has zero maintenance overhead.