Skip to main content
Home
GrN.dk

Main navigation

  • Articles
  • Cases
  • Services
  • Your Digital Project Manager
  • About Greg Nowak
  • Image Gallery
  • Contact
User account menu
  • Log in

Join my community / free newsletter — sign up here

Breadcrumb

  1. Home
  2. Cases

A 2020 phone game rebuilt for the browser, with a global leaderboard

Client
GrN.dk — internal build
Sector
Browser and mobile games
Period
Built 2020 · rebuilt and relaunched July 2026

veganpower.grn.dk ↗

Vegan Power running in a browser tab on a phone-shaped screen: seven full hearts and the score line "Vegan Power: 1" across the top, a blue sky of cartoon clouds with two oranges and a pear falling through it, a chicken, a dog and a penguin drifting down among them, and the round yellow player waiting with its mouth open at the bottom of the play column.

At a glance

veganpower.grn.dk is Vegan Power, a catch-the-fruit arcade game with a rule you understand in one second: eat fruit, not friends. Fruit falls and you catch it. A chicken, a cow or a penguin falls and you dodge it — each one you hit costs one of your seven hearts. It began in 2020 as a small Flutter and Flame game for Android, released on Google Play that December. In 2026 it was taken apart and rebuilt: it now opens in any browser with no install and no account, keeps a global high-score table on its own small API, and carries a multiplayer beta where two to four players share one arena and shove each other off the fruit.

89 commits, 2020 to 2026 — the same game in two eras
34 game tests + 29 API tests gate every single push
20 Hz server-authoritative relay · 2-4 players · 90-second rounds

The challenge

The starting point was a five-year-old hobby game that only existed as an app. To play it you had to find it in a store and install it, which is a lot of friction for something that takes ninety seconds to enjoy. Inside, the code showed its age too: one long game loop that drew every element by hand, a high score saved only on the device, and no way to test any of the gameplay rules without running the whole app.

The brief for the rebuild was therefore not "add features". It was: make it playable instantly from a link, on a phone or a desktop, anywhere in the world; give the score somewhere to live so a run means something; and do it so that the thing stays cheap to run and can be maintained a card at a time rather than in long, risky sessions.

Two constraints made that harder than it sounds. First, a Flutter game in a browser ships a large graphics runtime before it can draw a single frame — and the server is in Europe while a good share of the players are in Asia, so "it works here" says nothing about how it feels there. Second, the headline feature people ask for — real-time multiplayer — is a physics problem, not a feature request: in a reflex game, the distance between a player's finger and the server is felt directly, and no amount of code makes the speed of light shorter.

The solution

The game. Five kinds of fruit fall (banana, orange, pear, strawberry, watermelon) and six animals (chicken, cow, dog, elephant, penguin, pig). Catching fruit scores, and four catches in a row without a hit start a multiplier that climbs to five times; a hit resets it and costs a heart, of which there are seven. The fall speed and your own speed both rise with the score, so a round starts gentle and ends frantic. Every catch plays one of thirteen little voice clips — the "yum" and "no!" noises are in a handful of languages, Danish, Polish, German and Thai among them — over a single jazzy loop, with a screen shake and a particle burst on impact.

A modern engine underneath the same game. The hand-rolled render loop is gone. The game is now an ordinary Flame game where the views are router pages, and the hearts, score, combo, buttons and leaderboard panel are all self-positioning components. Just as important, the rules that used to be tangled into the loop are now plain functions with no graphics attached — difficulty curve, board geometry, and the collision check that decides whether you caught something. That last one is a swept test rather than a snapshot, so a fast-falling fruit cannot teleport straight through the player between two frames. Thirty-four automated tests cover those rules, plus a golden image of the home screen.

Making it behave in a browser. Two things were learned the hard way and are now written into the code as warnings. The game only renders reliably as a bare game widget — every attempt to wrap it in a layout widget blanked the screen — so the letterboxing is done inside the game instead: one centred nine-tile play column that the background, the HUD, the buttons and every spawn anchor to, at any window size. And the graphics runtime was being served uncached, which meant roughly 28 KB/s to a distant player: a caching rule at the edge took that to around 60 MB/s worldwide, which is the difference between "black screen, must be broken" and "it just opens".

A small API of its own. Global scores run on a FastAPI service with a SQLite file behind it, on the same server, proxied at vpg-api.grn.dk. There are no accounts and no email addresses: identity is an anonymous id minted in the browser on first play, with an optional nickname that goes through a profanity filter, and a transfer code if you want to carry your profile to another device. Because a public score endpoint is an invitation, submissions are signed, timestamped, rate-limited per device and per address, and capped at a score no honest round can reach. (One detail worth remembering: the free certificate at the edge covers only a single subdomain level, so api.veganpower.grn.dk could never work and the API lives at vpg-api.grn.dk instead.)

Fruit Rumble, the multiplayer beta. Two to four players join a four-letter room code for a ninety-second round in a shared arena, where bumping into someone shoves them — steal the fruit they were lining up, or push them into a cow. The server owns the simulation and runs it twenty times a second, because otherwise two players will never agree about who shoved whom; clients send only their input. Your own character is predicted locally and reconciled against the server's acknowledgement, the rest of the world is interpolated through a buffer that sizes itself from the jitter it actually measures, and an on-screen NET readout shows the round-trip time, the jitter and the current buffer so the feel can be argued about with numbers instead of adjectives.

Shipping it, every push. A build runs within ten minutes of a commit and refuses to go out if anything is red: the analyzer, the thirty-four game tests and the twenty-nine API tests all gate it. A green build deploys the web version, purges the edge cache, builds a signed Android release, installs it on a real Android emulator and runs a launch smoke test — and only a passing smoke promotes the public download link, mirrors the file to Drive and uploads to the store's internal testing track. A version tag is what promotes a build to production. Either way an email arrives saying "ready" or "BLOCKED", with the reason.

Seeing it, not assuming it. A game that renders on a canvas shows nothing to a script that reads the page, so verification is done with real eyes: a GPU browser and a real Android emulator that are driven, screenshotted and checked. The picture at the top of this page was made that way — an agent opened the live site, waited for the first frame, tapped START with real touch events, played a round, and captured it.

The results

Vegan Power is live at veganpower.grn.dk: open the link and play, on a phone or a desktop, with no install, no account and nothing stored about you beyond an anonymous id in your own browser. The Android build is still there for anyone who wants it — a signed APK from the latest commit, plus the original 2020 release on Google Play.

The global high score works end to end: finish a round and the game-over screen shows the global top three and your own rank, served by the project's own API. That was confirmed in the same automated session that produced the screenshot above.

The running cost is deliberately close to nothing: static files behind a CDN, one small API process and a SQLite file that the nightly backup already covers.

What is not finished, in the owner's own words. Multiplayer is labelled a beta on the home screen because that is what it is. Moving the relay to a connection that lands on a nearby edge location cut the network round trip from roughly 250 ms to around 100 ms for players in Thailand, and the relay's own work is under a millisecond — but everything except your own character is drawn through a smoothing buffer, so opponents and fruit still arrive a quarter of a second behind your finger. The verdict after a real round was "better, but still not playable", and the honest answer is that closing that gap means predicting the whole world locally and judging catches against what the player actually saw. Those two pieces are designed and scoped; they are not built. Solo play, which is the game most people will open, is unaffected.

Update, August 2026. The game now tests itself at two levels: a white-box suite runs the real Flame engine headless (menu flow, golden-image rendering checks, silent sound doubles injected for CI), and a black-box smoke drives the actual Android build through Appium and Robot Framework on a real device-lab machine — tapping what a player would tap, asserting what a player would see. Both are wired into CI, so a regression fails the push, not the player.

The other thing this project demonstrates is how it was made: the whole rebuild came off a Trello board one card at a time, each picked up by an AI agent — the web build, the caching fix, the leaderboard, the engine modernisation, the multiplayer relay and the latency measurements are each traceable to the card that asked for them, including the ones where the user simply wrote "web build is not doing well on full screen" and got a root cause back. There is a plain-language write-up of the game itself here: Vegan Power: the little game about eating fruit, not friends.

Eat fruit not friends.

The whole design brief — the first line of the game's 2020 README
  • Flutter
  • Flame
  • Games
  • browser games
  • Android
  • Custom Development
  • AI agents

Got a project that needs the same kind of hands-on delivery?

Your digital project manager

Review Greg on Google

Greg Nowak Google Reviews

 

Written recommendations from Trafik og Veje, Aarhus Municipality (2011) and AgroTech (2010) — read them on LinkedIn.

Illustrated infographic summarizing: WordPress 7.1 Forces the Editor Into an iframe—Test Your Custom Blocks
WordPress 7.1 Forces the Editor Into an iframe—Test Your Custom Blocks
2026-08-15

WordPress 7.1 removes the non-iframe editor fallback. Learn how to audit custom blocks, test real workflows and fix compatibility issues before launch.

Illustrated infographic summarizing: GitHub will stop sending jobs to stale self-hosted runners
GitHub will stop sending jobs to stale self-hosted runners
2026-08-14

GitHub starts enforcing runner versions on August 24, 2026. Audit and upgrade self-hosted runners before builds and deployments start stalling.

Illustrated infographic summarizing: Your AI Agent Has Shell Access. What Can It Reach?
Your AI Agent Has Shell Access. What Can It Reach?
2026-08-13

A practical guide to mapping what a shell-enabled AI agent can reach, then containing its access to files, credentials, networks, tools, and high-impact actions.

Illustrated infographic summarizing: Cloudflare Changed DoH JSON. What Else Is Parsing DNS as Text?
Cloudflare Changed DoH JSON. What Else Is Parsing DNS as Text?
2026-08-12

Cloudflare’s DoH JSON change exposes brittle DNS parsing. Find affected scripts, test both formats, and choose a safer integration contract.

Illustrated infographic summarizing: Your Website Can Answer Questions Now. Should It?
Your Website Can Answer Questions Now. Should It?
2026-08-11

NLWeb makes conversational website search practical to deploy. The real question is whether your content, users and team are ready to support it.

Illustrated infographic summarizing: AI Search Finally Has Reports. Now Connect Visibility to Revenue
AI Search Finally Has Reports. Now Connect Visibility to Revenue
2026-08-11

Google and Bing now expose first-party AI search data. The real task is connecting citations and impressions to analytics, CRM outcomes, and revenue.

Illustrated infographic summarizing: The Bot Passed Your CAPTCHA. What Did It Do Next?
The Bot Passed Your CAPTCHA. What Did It Do Next?
2026-08-11

Passing a challenge is only one signal. Session analysis, server-side validation and endpoint-specific controls help reduce bot abuse without blocking customers.

Illustrated infographic summarizing: WordPress 7.1 Moves Image Work Into the Browser—Test Every Media Hook
WordPress 7.1 Moves Image Work Into the Browser—Test Every Media Hook
2026-08-11

WordPress 7.1 shifts image processing into supported browsers. Here is what to test across hooks, CDNs, formats, security headers, and fallbacks.

Illustrated infographic summarizing: Prompt Caches Have Write Costs Now—Audit What Your Workflow Reuses
Prompt Caches Have Write Costs Now—Audit What Your Workflow Reuses
2026-08-10

GPT-5.6 makes cache writes billable. See how to spot wasted writes, stabilise prompt prefixes, place breakpoints and measure whether caching pays.

Illustrated infographic summarizing: The AI Crawler in Your Logs May Be Wearing a Borrowed Name
The AI Crawler in Your Logs May Be Wearing a Borrowed Name
2026-08-09

A User-Agent is a claim, not proof. See how to verify AI crawler traffic before it shapes reporting, robots.txt decisions, or WAF exceptions.

More articles
RSS feed

Footer

  • All articles
  • Contact

GrN.dk — AI automation, web platforms, web optimization, data handling and logistics.

© 2026 GrN.dk · LinkedIn · Contact · AI automation in Danish: nowa.dk

Behind GrN.dk: Individual Entrepreneur Codecrafter · Tax ID 305669096 · Bakhtrioni St. 22, 0194 Tbilisi, Georgia · official business register