sammys.ai
← All posts

Notes on making small browser games

2 min readgamesweb

The games section launched with two tiny games. Neither took long to build, and that was the point. Some notes from the process.

Scope is the whole game

A snake game has maybe five rules: move, eat, grow, speed up, die. That's a weekend project with room left over for polish — and polish is what makes a tiny game feel finished rather than abandoned. Score persistence, a pause state, swipe controls on touch screens: each is an hour, and together they're the difference between a demo and a game.

Canvas, but let CSS pick the colors

The snake board is a <canvas>, but it reads its palette from the same CSS variables the rest of the site uses:

function readToken(name: string, fallback: string) {
  return getComputedStyle(document.documentElement)
    .getPropertyValue(name)
    .trim() || fallback;
}
 
ctx.fillStyle = readToken("--ember", "#f54e00");

Toggle dark mode and the game re-inks itself on the next frame. One design system, everywhere — including inside the games.

Keep React out of the game loop

React re-renders are for UI, not for a 10-tick-per-second game loop. The snake's state lives in refs; React only hears about it when the score changes or the game ends:

const snake = useRef<Point[]>([]);
const dir = useRef<Point>({ x: 1, y: 0 });
// ...the interval mutates refs and repaints the canvas directly

Finish and ship

The least glamorous lesson: a small finished game beats a big unfinished one every time. Ship the snake. The bigger ideas can wait their turn on the coming-soon card.