Skip to main content
GrN.dk

Main navigation

  • Articles
  • Cases
  • Contact
  • Your Digital Project Manager
  • About Greg Nowak
  • Services
  • Portfolio
  • Container
    • Excel Freelancer
    • Kubuntu - tips and tricks
    • Linux Apache MySQL and PHP
    • News
    • Image Gallery
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.

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

 

Illustrated infographic summarizing: AI Agents Need a Spending Brake, Not Just a Billing Dashboard
AI Agents Need a Spending Brake, Not Just a Billing Dashboard
2026-08-08

AI agent costs can climb inside a single workflow. Runtime budgets, loop detection, outcome metrics, and safe handoffs keep that spending under control.

Illustrated infographic summarizing: Drupal 12 Slipped to December. Drupal 10 Still Runs Out of Road
Drupal 12 Slipped to December. Drupal 10 Still Runs Out of Road
2026-08-07

Drupal 12 arrives as Drupal 10 support ends in December 2026. Moving to Drupal 11.3+ first keeps two mandatory upgrades manageable.

Illustrated infographic summarizing: EU OpenAI Residency Is a Migration Project, Not a Dashboard Toggle
EU OpenAI Residency Is a Migration Project, Not a Dashboard Toggle
2026-08-05

An EU-resident OpenAI API setup needs a new project, regional routing, dependency and state migration, compatibility testing, and clear governance evidence.

Illustrated infographic summarizing: AI Images Need a Chain of Custody, Not Just a Disclosure Label
AI Images Need a Chain of Custody, Not Just a Disclosure Label
2026-08-04

AI image labels are only the endpoint. Learn how to test C2PA credentials through editing, CMS, CDN and agency handoffs while preserving evidence.

Illustrated infographic summarizing: MCP Just Went Stateless: Audit the Integrations Behind Your AI Tools
MCP Just Went Stateless: Audit the Integrations Behind Your AI Tools
2026-08-03

The 28 July 2026 MCP release removes protocol sessions and changes discovery, tasks, caching, OAuth and tracing. A practical guide to auditing the move.

Illustrated infographic summarizing: SEO Trends for 2026: What Actually Changed Since 2024
SEO Trends for 2026: What Actually Changed Since 2024
2026-08-03

A practical guide to what changed in SEO between 2024 and 2026, from AI and multimodal search to Core Web Vitals, privacy and local visibility.

Illustrated infographic summarizing: INP and Green SEO Share a Backlog: Cut the Work Every Visit Repeats
INP and Green SEO Share a Backlog: Cut the Work Every Visit Repeats
2026-08-03

INP and sustainable web work often expose the same waste. Use field data, profiling, caching and performance budgets to build one practical backlog.

Illustrated infographic summarizing: AI crawler policy now has verbs: separate search, RAG, and training
AI crawler policy now has verbs: separate search, RAG, and training
2026-08-02

AI crawler rules now need separate decisions for search, RAG, and training, backed by practical testing across robots.txt, CDNs, WAFs, and CMS controls.

Illustrated infographic summarizing: WordPress Supports Old PHP; Your Production Server Shouldn’t
WordPress Supports Old PHP; Your Production Server Shouldn’t
2026-08-01

WordPress still runs on legacy PHP, but compatibility is not a security policy. Build and test your upgrade path before PHP 8.2 support ends.

Illustrated infographic summarizing: The AI-built tool your team relies on needs an owner
The AI-built tool your team relies on needs an owner
2026-07-31

AI-built internal tools can become business-critical before anyone owns them. Here is how to secure, review, monitor, and retire them without blocking useful work.

More articles
RSS feed

Footer

  • All articles
  • Contact

GrN.dk web platforms, web optimization, data analysis, data handling and logistics.