Skip to content

Case study · Gaming · A JQiT product

Paulie Paulie.

A 3D open-world MMO with flying racing that runs in an ordinary browser tab, at 60 frames per second on a phone.

The game began at home: the family's real Blue-crowned Conure, a Warcraft childhood and a Minecraft imagination. It is now a live product on its own domain, and this page is our engineering record of it. What we built, the architecture underneath it, and the security work that shipped with it rather than after it.

The game itself lives at pauliepaulie.com. Play it there; read on for how it works.

The home base at dusk, with the player character standing among the buildings.
Home base
A floating island high above the world, reached in flight.
The floating island
A boss fight in progress against a large enemy.
A boss fight
Two players duelling in the open world.
A player-versus-player duel

What we built

An open 3D world with WoW-style progression, real-time multiplayer, player-versus-player duels, boss fights, a cosmetics store and aerial racing. It loads from a URL. There is no install, no launcher and no app store between a player and the game, which is also what makes the engineering interesting: everything below had to be achieved inside a browser's limits.

Runs onAny modern browser, phone first. The performance floor is 60 frames per second on mid-range mobiles, held by per-device budgets and an adaptive quality scaler.
RenderingWebGL through Three.js, written in plain JavaScript. No TypeScript, no bundler, no build step: the files that ship are the files we write.
MultiplayerA realtime backend on InstantDB: presence, rooms, topics and transactional writes, with a thin sync layer over them.
Performance disciplineObject pools for anything created more than once a frame, module-scope scratch buffers instead of per-frame allocation, and a physics step budgeted at under 1.5 milliseconds at the 99th percentile.
PlatformsOne codebase, built to ship to web, Android, iOS and Steam in that order. Platform behaviour sits behind a thin adapter layer, never in forks of the game logic.

How it is built

The unusual choice is the absence of machinery. The client is hand-written JavaScript served as-is, which keeps the loop between an idea and a running game very short, and makes every shipped byte one a person wrote and can read. Discipline replaces tooling: one system per file, balance numbers kept in data files rather than code, and a documentation wiki where each design document is the single source of truth for its own scope.

Architecture decisions are recorded as ADRs and treated as immutable once accepted. A decision that turns out wrong is superseded by a new record, never quietly edited, so the reasoning trail behind the game stays honest. The same delivery framework runs the project day to day: a task board with explicit gates, continuous integration that lints and validates on every change, and a dashboard regenerated by tooling so it cannot drift from the truth.

Where the browser fights back, the game adapts rather than degrades. Boot probes measure the device before committing to a quality tier, a watchdog heals lost WebGL contexts after a phone sleeps, and collision geometry is pre-baked so the client never pays to compute it.

Security, built in from the start

JQiT is a security consultancy, and the game is held to the same standard as our client work. The principle throughout is that the client is never trusted with a decision that matters.

PurchasesThe browser sends product identifiers, never prices. A Cloudflare Worker builds every checkout server-side with Stripe as the merchant of record, and entitlements are granted only by signed webhooks. Refunds revoke automatically.
IdentityEvery server decision reads the caller's own token. There is no client-supplied account id anywhere in the API surface.
Age gatingA neutral date-of-birth screen, with the applicable minimum age decided at the edge from the connecting country. The date of birth itself is never stored, only the outcome of the check.
AbuseCloudflare Turnstile proves a human before an account can be created, server-set stamps are field-locked so a client cannot forge them, and write rates are limited per user and per address.
ProcessEvery change to the payment surface must pass a recorded security review bound to the exact code being merged, and continuous integration blocks any shipped dependency with a known vulnerability.

From a real bird to a playable one

The player character is the family's actual bird, carried through four stages of art direction until he could fly in a browser.

Photograph of Paulie, the family's Blue-crowned Conure.
The real Paulie
Paulie drawn by hand, perched on a branch.
Hand-drawn
A caricature of Paulie.
Caricature
The low-poly 3D game model of Paulie.
The game model

See it running

The quickest way to judge a browser game is to open it.

Play Paulie Paulie