Eleven Browser Games in a Week — What a Design System Buys You
play.pickuma.com now has eleven games. After the first two, the bottleneck was no longer game logic — it was the chrome around each game. Here's the design system that made the next nine fast.
A week ago play.pickuma.com had two games. As of today it has eleven. The new nine took less wall-clock time per game than the first two did — by a wide margin. The interesting part wasn’t the game logic. It was the chrome.
The eleven
In order of build time, fastest first:
- Reaction — wait for green, click ASAP, five rounds median. 1 hour.
- Numbers — Schulte table, click 1 to N in order on a shuffled grid. 2 hours.
- Color Match — a hex code, twelve swatches, pick the matching one. 2 hours.
- Color Echo — Simon-style memory, every round adds one. 3 hours.
- Perfect Square — draw a closed square in one stroke; we compute corner angles and side ratios. 4 hours.
- Stack — drop a moving block on a tower; misaligned edges fall off. 4 hours.
- Knife Hit — throw knives at a rotating target; don’t clash with knives already stuck. 5 hours.
- Crossing — Frogger-style endless lane crossing, one button to step. 5 hours.
- Paper Plane — Flappy-style one-button side-scroll. 5 hours.
- Stop at 7.77 — hidden timer, stop at exactly 7.77 seconds. 8 hours. (Was first; spent more time on the dot animation than the timer logic.)
- Eagle Run — third-person 3D-ish flight survival on canvas 2D. 2 days. (Also first; complex projection logic.)
Eleven games. Two days of game logic. The rest was shared infrastructure that paid back nine times over.
What’s shared
After the first two games shipped, I extracted a DESIGN.md — well, a private one — codifying everything every game needed. The pattern is the same one shadcn-ui uses for its component library: name what’s shared, name what’s per-instance, write down the contract.
Per-instance: one CSS variable
Each game gets one signature accent color via --game-accent. Stop at 7.77 is blue, Eagle Run is amber, Numbers is mint, Crossing is orange. Inside each game route:
<section style="--game-accent: #34d399"> <!-- everything inside derives from this --></section>Buttons, score color, hover states, OG image, particles — all reference var(--game-accent). To brand a new game I write the hex once.
Shared: everything else
The same code handles every game’s:
- HTML structure (header strip, stage area, overlay card, share panel)
- Buttons (
.btn-pillfor primary action,.btn-rectfor secondary chrome) - Motion curve (
cubic-bezier(0.16, 1, 0.3, 1)at 180ms, site-wide) - Score readouts (JetBrains Mono Variable, tabular numerals,
font-variant-numeric: tabular-nums) - Bouncing dot animation (used by Stop at 7.77’s hard mode, available to anyone)
- Stage backdrop (dot-grid radial-gradient pattern)
- Result reveal (220ms spring-out keyframe)
Pick up the per-instance variable, drop in your game’s mechanics, ship.
What the games share at the JS level
Every game has the same five things:
- A state machine —
idle → playing → result(sometimesmenu → playing → dead). - A
performance.now()clock for any time-sensitive measurement. - localStorage personal best —
localStorage.setItem('<game>-best', value). - A share function —
navigator.sharewith clipboard fallback, same string template across games. - Three GA4 events —
play_start,play_end,share_click, with consistent param names so all eleven funnels are comparable.
Once those five are stamped, the only original code in a new game is the loop in the middle: spawn obstacles, accept input, compute score. Eagle Run’s was 290 lines. Reaction’s was 60.
Builds and OG images
Both projects (pickuma.com and play.pickuma.com) are Astro 6 → Cloudflare Workers + Static Assets. The play project’s build runs three things in order:
bun scripts/gen-og.ts # render 11 PNGs from SVG templatesastro build # static site generationbun scripts/post-build-patch.ts # inject SESSION KV idEach OG image is a 1200×630 PNG rendered server-side at build time via @resvg/resvg-js. Template-driven: I describe a game with { slug, accent, display, title, tagline, url } and the renderer produces a card with the game accent glow, the dot-grid backdrop, and the title block. Eleven cards generate in under a second total. No edge function, no dynamic OG, no infra to maintain.
What it cost
Eleven games, each with:
- One Astro page (averaging 50 lines)
- One JS file (averaging 200 lines)
- One pre-rendered OG image
- One spot on the hub grid
- One row in the itch.io upload script
- Three GA4 events
- A
Cmd+Clickaway from running locally
Total disk: 4,200 lines of code across pickuma-play/. Total commit count: 19. Wall clock from git init to game 11: 9 days.
The interesting unit economics: the first game cost a day. The last three games cost a half-day each. The design system absorbed every cost that didn’t have to be repeated.
Try them
The full hub is at play.pickuma.com. All eleven are mobile-friendly (touch is mapped where it makes sense), all are free, none ask for an email.
If you build something on a similar stack, send it. I’d particularly like to see what happens if someone applies this design-system-first pattern to a single deeper game instead of a wide portfolio of shallow ones.
Related tools
Beehiiv
Newsletter platform with built-in ad network and Boost referrals.
Try Beehiiv →
Webflow
Visual site builder with real CSS export and a CMS that scales.
Try Webflow →
Some links above are affiliate links. We may earn a commission if you sign up. See our disclosure for details.