Overclock looks like a game capture site, but there isn't a single image file in the repository. Every screenshot, icon and face is drawn at runtime by ~200 lines of canvas code — no framework, no animation library, no build step. Here's how.
An indie roguelike launch page has one honest advantage over a AAA one: the studio can show its actual craft instead of a cinematic trailer. So the site's pitch is the demonstration — the hero "key art" is a live pixel renderer, the screenshots are the same renderer in four palettes, and the patch notes type themselves out in a terminal. If the page itself feels like the game, the wishlist button doesn't need to shout.
The layout borrows three shipped patterns (researched on Mobbin): the streaming-service title hero (logo lockup + metadata strip + loud/quiet CTA pair), the store-page "latest updates" version notes promoted to a full devlog section, and the marketplace thumbnail-rail screenshot gallery.
image-rendering:pixelated — the browser does the chunky upscale for free.cubic-bezier(.12,.8,.16,1) and a
chunky steps(5,end) — every hover, reveal and blink snaps through frames like a
sprite sheet instead of gliding.One painter function draws every dungeon on the site. It's deterministic: a seeded mulberry32 stream decides bricks, cracks, crystals and furniture, so the same seed always produces the same room — at 8 ticks per second, sixty times a minute, without the scene rearranging itself:
const mulberry32 = (a) => () => { /* deterministic 0..1 stream */ };
// layout, bricks, cracks, crystals: from the SEED stream
// flames, fog, portal breathing: from a tick HASH
const hash = (a, b) => { /* stateless — never disturbs the seed */ };
paintDungeon(ctx, 192, 128, PALETTES.crypt, seed, tick, knight);The split matters: anything structural reads from the seeded stream, anything alive (torch flames, drifting fog dither, the portal glow) reads from a stateless hash of the tick. That's why the room holds still while its torches flicker.
Sprites are authored as ASCII maps — a knight is twelve characters wide, and each character indexes a palette:
const K_BODY = [
'....PP......', // P plume (magenta — amber in god mode)
'...PHHHH....', // H helm
'..PHHHHHH.S.', // S sword
'..HHVVHH..S.', // V visor
...
];
drawMap(ctx, K_BODY, KNIGHT_COLORS, x, y, flip);The walk cycle is three leg frames swapped at 8 fps, with a one-pixel bob. The same
drawMap draws the feature icons, the platform glyphs and the two founder faces.
The four "screenshots" are the same painter with different palettes and seeds — flooded floors
get a shimmer band, the furnace gets rising embers, the garden grows dithered vines.
The CRT is layered, cheapest-first, and every layer is plain CSS:
repeating-linear-gradient(0deg, rgba(4,2,10,.22) 0 1px, transparent 1px 3px),
plus a stronger copy scoped inside each bezel. A 5s steps() opacity keyframe
adds mains hum.scaleY(.004) and snaps
open like a tube warming up.backdrop-filter:hue-rotate() jump via steps() while
main jitters ±5px and headings get an RGB-split text-shadow — for 130ms:// fires ONLY on scroll-section change, never on focus,
// never with reduced motion, and never twice within 6s
if (!armed || reduced() || now - lastGlitch < 6000) continue;
document.body.classList.add('is-glitching');
setTimeout(() => document.body.classList.remove('is-glitching'), 140);.sr-only block and the animated layer is
aria-hidden — screen readers never hear a half-typed word.aria-hidden inside a role="img" figure with a written scene
description.role="status", the knight's plume goes amber, and the HUD grows to six hearts.Everything is relative-path and build-free, so deploying is three commands:
gh repo create overclock-games --public --source . --push
gh api --method POST /repos/USER/overclock-games/pages \
-f 'source[branch]=main' -f 'source[path]=/'
# live at https://USER.github.io/overclock-games/ in ~1 minA .nojekyll file tells Pages to serve the folder as-is. No pipeline, no CI — the
same way the site has no dependencies.
Overclock is a design-showcase concept — the studio and the game are fictional, the renderer is real. See the repository README for the full demo-vs-real map.
← back to OVERCLOCK