Eleven Browser Games in a Week
All eleven live at play.pickuma.com. After the first two, the bottleneck was the chrome around each game, not game logic. The design system fixed that.
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 templates
astro build # static site generation
bun scripts/post-build-patch.ts # inject SESSION KV id
Each 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.
Related reading
2026-09-02
OpenAI Deployment Layer: The Assistants API Precedent
OpenAI shipped the Assistants API in November 2023 and marked it for sunset 16 months later. That precedent is how to price the new deployment stack.
2026-08-21
701 Bad Internal Links Before 49 Good Ones
A phrase-matching script inserted 750 links across 269 MDX articles. Here is where they failed, and how claim-matching cut the review pile to 128.
2026-08-21
Cloudflare Web Analytics via GraphQL: the siteTag Filter
Why accountTag and siteTag differ in rumPageloadEventsAdaptiveGroups, how the limit argument truncates silently, and which fields we did not verify.
2026-08-21
Bing Webmaster API's 100-URL Cap: 289 URLs, Three Days
Quota is 100 a day against 1300 a month, GetQueryStats was still empty at the end, and two error shapes will kill a cron job.
2026-08-19
IndexNow Batch Mode: 286 URLs Per Publish Down to 0
Bing flags full-sitemap submissions as batch mode. The ~40-line lastmod diff that fixes it, the precondition it needs, and two ways it silently breaks.
Get the best tools, weekly
One email every Friday. No spam, unsubscribe anytime.