WizusLabs Engineering

WizusLabs Engineering Blog

Build-in-public writing about how an AI-native studio actually builds software — the engineering decisions, the trade-offs, and the honest detail behind the games we ship.

This is the engineering side of WizusLabs, written in plain English. Where the guides explain our games to the people who play them, the blog explains how the studio works to the people who build things — long-form posts across five pillars: dimensionality, frameworks, data, craft, and the AI-native studio itself. Every empirical claim is sourced, every post stands on its own, and new pieces land here as we write them. You can also subscribe via RSS.

Subscribe via RSS — new posts land in any feed reader (Feedly, NetNewsWire, …).

Latest posts

Sixteen locales, one grammar: the localization assumptions English hides

A localization defect is rarely a translation error — it is usually a correct decision made in the wrong grammar. Our games ship in sixteen languages; every string here was correct and every gate stayed green. A screen reader spoke a plural noun over a count of one in French and Italian, and it fired on every one-star clear. An ARB =1 selector chosen on purpose is rewritten by gen-l10n into the CLDR one category, which in Hindi admits zero too — and Hindi is no edge case but a four-member set including Vietnamese. Then the oracle: in English incorrect contains correct, so an assertion meaning “this announced correct” is satisfied by the announcement for incorrect in seven of sixteen locales. It fails toward pass on the outcomes it exists to distinguish. Including why a prefix test and a suffix test partition the corpus with neither sound everywhere.

Frameworks · 2026-08-03

Read back what you published: four ways the two store APIs disagree

Deciding to verify a store write is the small half. Comparing it on the right basis is not, and the two stores need different equality tests on the same bytes: Play drops the POSIX trailing newline on persist, Apple keeps that byte, so carry one store’s rule across to the other and you get 0 of 18 on a flawless upload — a fabricated catastrophe from a check that was working perfectly and asking the wrong question. A first-hand account of one game’s copy and screenshots pushed to both stores in 18 locales, and the four ways the two APIs disagree about what a write even means: what a body replaces, when a field is writable, what order is kept, and what is atomic with what. Including the 409 that corrected a claim we had already put in writing, and why 204 is the emptiest promise in HTTP.

Studio · 2026-07-31

Every zero has two explanations: the control your check is missing

A check has two ways to come back clean: the condition really is absent, or the instrument never ran. Both print the same zero. On one of our staging cuts the pre-promotion gate returned empty on a release binary that genuinely carried the marker — the output had been captured into a variable instead of piped. Four broken instruments, one indistinguishable result, and the control that separates them. Plus why one control is not enough.

Craft · 2026-07-30

Two homes for one rule: ‘extract’ is half a verb

A refactor is not finished when the new home works — it is finished when the old site carries no independent copy of the rule. Our own decision record moved an ad-eligibility predicate into one place so there would be a single home for it, named the original five times, called the duplicate removed, and filed the actual removal under follow-up, where it stayed. One page, two tenses. For the next three days both homes were live, and the next two fixes each went to the wrong address — both shipping with green tests, because a test that the new home behaves correctly passes just as happily with the duplicate still running. A person caught it, not a check. Why the guard has to be an oracle rather than a same-value check, how we bite-proved it on a private predicate no test could reach without mutating a line, and the third copy we found and deliberately left alone.

Craft · 2026-07-30

Pausing is the easy half

Gate the update loop and the game looks properly paused — which is exactly why the rest goes unnoticed. Everything that measures the game also has to agree it is stopped, and the pause has to know who is holding it. A first-hand account of rediscovering that shape in five of our own games in one week: a progression gate fed by a wall clock that kept climbing while the simulation sat correctly frozen; a win overlay that painted over a puzzle without absorbing taps, so two touches could restart a finished clock; an inner overlay closing and un-pausing the game underneath an outer one still on screen; and why we rejected the cheaper fix of subtracting the paused time.

Craft · 2026-07-29

A guard nobody has seen fail

One of our localization checks passed green for two days beside a file it could not, in principle, detect — an app_ar.arb compiled into every binary that no player could select — because the check enumerated the very list it was validating. A first-hand account of the two rules that came out of it: derive the set you are checking from the authority (the disk, the call sites) and never from the list under test, with every exemption declared data carrying a reason; and the one that matters more — a guard nobody has seen fail is indistinguishable from a guard that cannot fail, so the deliverable of a new guard is evidence it can go red, restored afterwards by hash rather than by eye.

Studio · 2026-07-28

Valid does not mean ready

Upload the first build to a brand-new App Store Connect record and it climbs to processingState=VALID — the status is green, the spinner is gone, and there is still nothing you can hand a tester. A first-hand account of the first-cut-only trap: why VALID is a fact about the binary, not about whether a human can install it; why a fresh app stalls at MISSING_EXPORT_COMPLIANCE with no internal beta group while its shipping siblings have one; the setup steps that make the first build testable; and why the trap fires exactly once per app, which is precisely why it keeps catching people.

Studio · 2026-07-27

A debug switch that ships in the release build

We compile a debug switch straight into the release build we hand to testers — an artifact identical in shape to the one that reaches the store — and the discipline around it is the only reason that is safe. A first-hand devlog on the compile-time flag, the ahead-of-time quirk that deletes the very token you would grep for (so DEV_UNLOCK is gone from both builds), and the print()-side-effect marker that lets the binary prove which build it is: strings | grep returns one in a QA build and zero in production.

Studio · 2026-07-27

The locale that breaks your layout

We laid our arcade game’s interface out in English, tested the overflow in English, and everything fit — then localized it to five languages and watched a control quietly run off its own edge in German. A first-hand devlog on the trap an English-only overflow test cannot catch: why a longer locale (German compound words especially) overflows at the default 1.0× text scale before any accessibility scaling, why a 2× English test is a different failure mode entirely, and the cheap parameterized guard — 42 cases across the densest screens, in de, es, and pt — that made a longer locale not “done” until its layout is verified.

Craft · 2026-07-27

Never name the other store

We ship the same game to two stores that each refuse to admit the other exists. A first-hand note on the cross-platform reference rule — why naming Android in an iOS listing gets it rejected under App Store Guideline 2.3.10, why Google enforces the mirror image, where the forbidden words hide (keywords, release notes, a Pixel in a screenshot), and the two-line grep audit we run before every upload so the same sentence that fails both reviews can never ship.

Studio · 2026-07-26

When two agents edit one file, the last write wins

Run two AI agents at once against the same file and you have not doubled your output — you have started a silent argument about whose edit survives, with no merge conflict and no error to warn you. A first-hand account of the shared working tree that makes hot files (game_bloc.dart, the app root, pubspec.yaml) revert with no trace, and the three rules that fixed it: one owner per file per batch, grep for a unique marker before you trust the change landed, and never “recover” with git stash or reset --hard in a tree you share.

Studio · 2026-07-25

A version number is a promise; a build number is a receipt

Every app ships two numbers that look like one: the marketing version a human reads and the build number the store orders by. A first-hand account of why automation may bump the receipt but only a human moves the promise — semantic versioning as a claim about the size of a change, why “ship it” never authorises a version bump, and why the build number has to be the same integer on both stores or the crash reports stop making sense.

Studio · 2026-07-24

The permission you don’t use is a liability, not a convenience

We told Apple one of our games plays audio in the background; the game does the opposite — it goes silent the instant you leave it. A first-hand postmortem on declaring an iOS capability you don’t use (UIBackgroundModes: [audio]), the App Store Guideline 2.5.4 rejection it caused in Sudoku on 2026-05-22, the identical rejection it caused in the tank game on 2026-07-09 because we fixed the file and never wrote down the lesson, and the audit that finally made a habit into a rule.

Studio · 2026-07-23

One canonical home: the day we deleted 800 pages of our own site

We made our website easier to find by deleting most of it. A first-hand devlog on why two live origins — wizuslabs.com and the legacy github.io — were one site competing with itself for ranking signal, how we picked a single canonical home and stripped the other from 803 files to 7 (path-preserving redirects, removed pages 404→noindex), and the trade-off we took on purpose: no fallback host, a redirect shell to maintain, and a hard guard so we can never re-push the duplicates back.

Craft · 2026-07-22

Staging has to lie exactly like production

Why our test builds carry production third-party SDK keys, not sandbox — keeping the staging binary byte-identical to the one we ship, the “wrong API key” trap that blocks a tester before they play, and the single difference we always flag.

Craft · 2026-07-21

Why a well-behaved game goes silent the moment you leave it

A well-made game cuts its sound the instant you swipe away — and that silence is the most respectful thing it does. A first-hand devlog on pausing audio the moment focus is lost via Flutter’s app-lifecycle callback, why a game must never declare the iOS background-audio capability it does not use (both against the rules and contradicted by its own behaviour), and the recurring App Store rejection we caused twice before a local audit script finally made the fix stick.

Craft · 2026-07-20

Deterministic by design: seeding randomness so bugs reproduce

The most useful thing a game engine can give you is the ability to make a bug happen again, on command. A first-hand devlog on how our arcade engine gets there — one seeded generator owned by the engine, a canonicalized state hash that fingerprints a moment of play, and deterministic replay from a seed and a list of inputs — plus the sub-stream we keep deciding not to build, and the discipline tax the whole thing costs.

Frameworks · 2026-07-19

Consent without dark patterns: the first screen a free game is judged by

The consent screen is the first real thing a free game shows you, and it is exactly where free-to-play quietly turns adversarial. A first-hand account of how we wire GDPR/UMP consent and Apple’s App Tracking Transparency — no pre-ticked boxes, no guilt-trip asymmetry, the correct prompt order, and an honest ‘no’ that still works — including the trade-off we accept on purpose: a fair flow measurably lowers the opt-in rate.

Studio · 2026-07-18

The hidden cost of renaming a shipped app

We renamed a shipped game from Iron Blitz to Iron Swarm, and the new name was the easy part. A first-hand devlog on what a rename actually touches: canonical URLs baked into binaries already in the field, redirect stubs you must never delete, a version manifest that has to answer to both names, and the permanent identifiers — package, bundle, App Store number — a rename can never move.

Craft · 2026-07-17

Designing an app icon that survives the home screen

We had a Boardlore icon we liked at 1024 pixels — a gold knight on dark wood. Then we judged it the way players actually see one: masked to the iOS squircle and shrunk to a home-screen thumbnail. A devlog on why concept and legibility are two separate tests, why a pinwheel of pieces blurred to a blob while an open book survived, and why we redrew the winner coarse and bold to read at 120 pixels.

Craft · 2026-07-16

Write the canonical form: a lenient reader hid a mess

A strict validator refused an App Store link that every browser accepts — because the browser silently follows a 301 redirect the validator will not. That same forgiveness had been hiding an inconsistency across our own links: some canonical, some bare, none broken, none noticed. A devlog on lenient vs strict readers of the same data, and why you write the canonical form everywhere.

Craft · 2026-07-15

The browser tells the truth: a Back-button bug we almost fixed wrong

We had a confident, framework-deep theory for why the browser Back button did nothing on our Iron Swarm web build — and a fix designed and QA’d against it. Then we drove a real headless browser through the exact flow, and the actual cause was far simpler: a ‘Play on web’ link that opened the game in a new tab, where Back has no previous page. A devlog on reproducing before you theorise.

Craft · 2026-07-14

Designing games that survive interruption

Mobile games are played in stolen minutes, so the interruption — a call, a screen lock, an app switch, an OS kill — is the normal case, not the edge case. The craft of surviving it: treat the fragment as the unit of play, save on the way out and never on quit, pause the instant focus is lost, and resume without dropping the player into a live hazard.

Craft · 2026-07-13

Designing game audio that players don’t mute

Most phones live on silent, and the mute toggle is the most honest review a game’s audio will ever get. The craft of sound players keep on — design for silence first, never punish with audio, and spend loudness like a budget, with the fanfares saved for moments that deserve them.

Craft · 2026-07-12

How we generate and grade Sudoku puzzles

A first-hand look at how our Sudoku app builds puzzles: fill a complete grid, dig holes while preserving a single solution, verify uniqueness with a solver, and grade difficulty by the techniques a puzzle demands — not by counting clues.

Frameworks · 2026-07-10

An AI QA gate for games: what it catches, what it misses

A first-hand, honest account of the automated QA gate every change clears before we ship a game — what it reliably catches, and the things it structurally cannot see, which is why a human still signs off.

Studio · 2026-07-10

Designing games colorblind players can actually play

Around 1 in 12 men and 1 in 200 women have some colour vision deficiency, and color-only encoding quietly locks them out. Here is why it fails, and the practical design fixes — shape, label, contrast, safe palettes, colorblind modes, and simulator testing — that let everyone read the game.

Craft · 2026-07-10

What’s charting and why — July 2026

Our first monthly read on what is actually charting and why: Cyberpunk 2077 back above 100k concurrent on Steam, the dated PC peak leaderboard (CS2, Dota 2, PUBG), and June 2026’s top mobile games by rank.

Data · 2026-07-09

What 2026’s top games have in common: a data teardown

A sourced teardown of the patterns that actually unite 2026’s top games — the $197B market and its platform split, free-to-play monetization, and why retention is a percentile band, not an average.

Data · 2026-07-09

Unity vs the alternatives in 2026

Unity, Unreal, Godot, GameMaker, Bevy, Flame and the rest in 2026 — with the one caveat most engine comparisons skip: the ranking flips depending on whether you count Steam releases, revenue, or a developer survey.

Frameworks · 2026-07-09

Building games with an AI agent crew: our actual pipeline

A first-hand, honest account of how an AI-native studio actually ships games: an orchestrator plus specialist agent crews, review gates, and a human who stays accountable — including where the model works and where it breaks.

Studio · 2026-07-09

← Back to home