Wordulate
The Guardrails We Had to Earn
Recent Wordulate builds taught us that offline play, rewarded ads, and account recovery are not checkboxes. They are promises, and every promise needs a boundary players can trust.
Back to blog
The loading screen disappeared. For a moment, the game was there. Then the internal build crashed.
That is one of the useful things about putting a game on an actual phone: the phone has no interest in the story you were planning to tell about it.
In our last studio note, I wrote about the work before the finish line. Those were the foundations we were building around Wordulate so a small team could move quickly without losing context, ownership, or player trust. Since then, the game has grown from 50 curated progression levels to 100. We have continued refining the Daily Puzzle, rewards, clues, and the first few minutes of play. More signed Android and iOS builds have made their way into internal testing.
That is the progress-list version. The more honest version is that our most valuable work came from the moments when those systems failed.
After 30 years developing software and 20 years making games, I know how easy it is to mistake motion for readiness. A feature exists. A check is green. A build finishes. Everyone wants to move on. Wordulate has been a useful reminder that none of those things necessarily means a player can trust what is in their hands.
Word-game players understand that trust instinctively. Reject a familiar word, lose a hard-earned reward, forget a Daily result, or return to find progress missing, and the technical explanation does not matter. The game broke the agreement.
Wordulate is still in internal development. This is not a launch announcement. The ads discussed here use test inventory, the builds remain internal, and account recovery is not finished. What has changed is our standard for saying something works.
A phone can overrule a green checkmark
The startup crash arrived after a change to how the app restored saved state and reconnected to the network. The code looked reasonable. Automated checks passed. Focused tests passed. On iOS, the transition from loading screen to game still failed.
We reproduced the problem, fixed it, and quarantined the affected builds. Then Android reported its own post-loading crash. One attempted replacement stopped before it produced an installable file, but its version had already been claimed.
The tempting response would have been to reuse the number and try again. We did not.
A build number now belongs to one source, one purpose, and one attempt. If that attempt fails, the number is spent. We close it honestly, reserve the next one, and preserve the history. Creating a build is also separate from permission to distribute or submit it. Each step needs its own evidence and approval.
We strengthened the build test around the exact version we intend to distribute: start fresh, start again with saved progress, reach the first playable level, make sure the board responds, and capture useful evidence when it does not. A passing code test still matters. It simply does not get to impersonate a game running successfully on a device.
For game developers, the lesson is familiar but easy to postpone: the build pipeline is part of the product. If it produces something we cannot identify, reproduce, or truthfully validate, it can damage player trust before anyone reaches the board.
Offline play is not a switch
Wordulate has been designed with offline play in mind from the beginning. It is easy to say that sentence. It is much harder to answer the player questions hiding inside it. What happens if I finish a level without a connection? What if I earn something, close the app, and reconnect later? Which result should the game trust if the phone and server briefly disagree?
Our first broad offline approach exposed how many answers we had not made precise enough. In one internal build, the game could remain stuck after reconnecting even though the server had already reached a final answer. Fixing that uncovered more trouble around restarting, reconnecting, stale messages, and restoring earned progress cleanly.
At that point, we stopped expanding the feature. That decision mattered. It is difficult to pause something after spending real time on it, especially when the broad idea appears to work. But "usually works offline" is not a promise I want to make to players.
We reviewed the design again across Client engineering, Server/shared engineering, Production, and the Game Director. The replacement is narrower and more deliberate: offline play now runs inside a tightly bounded authority model, and reconnection resolves against the server before progress or value is finalized. We added deterministic recovery coverage for the failure paths that mattered most in testing. Installed tests stop at the first serious failure instead of continuing and producing a reassuring average.
That work took more cycles than the original implementation. It also gave us a better definition of "offline." Not "the screen still opens," but "the player can trust that progress and earned value reconcile cleanly after an interruption or reconnect."
A rewarded view has to mean exactly one reward
The same principle shaped our test-ad work.
An ad appearing on screen is not a completed integration. For a player, the contract is simple: if the game offers a reward and I earn it, the reward should be there. A restart or a momentary interruption should not make it disappear or duplicate it.
We therefore treated rewarded fulfillment as authoritative game state, not a visual event. The app and backend now validate that earned rewards reconcile reliably across interruption and recovery without duplicating value.
We kept the entire path limited to internal testing and test inventory. When one external approval path stopped being useful at this stage, we deferred it rather than letting it block core quality work and continued with a guarded Google test path.
Then the Android build failed.
Two parts of the Android toolchain were speaking incompatible versions of Kotlin. We could have changed a number, sent another cloud build, and hoped. Instead, we pinned a compatible set of native dependencies and added a local release check that exercises the real Android build path before we spend another one-shot cloud build.
The failure became a gate.
Deployment needed the same honesty
The backend had its own version of the same lesson. A single "deploy" action was doing too much at once: preparing a candidate, exposing it to traffic, checking it, and hoping rollback remained understandable.
We split the path. Staging can now prepare a candidate without player traffic, test that exact candidate, and promote it only through a separate decision. The system verifies what is moving forward, and rollback is part of the procedure rather than an emergency improvisation.
That process caught several defects in the release tooling itself: a flaky timeout check, a generated name that exceeded a platform limit, an artifact-verification mistake, and a candidate whose relationship to the latest source had become unclear after unrelated work moved forward.
None of those failures reached a public production service. They still mattered. Release tooling that cannot prove what it is promoting is not a neutral inconvenience. It is a quality risk.
Each failure became another mechanical check. That may be the least glamorous sentence in this post, but it is the work that lets a small studio move quickly without relying on memory and luck.
The feature we refused to fake
The newest hurdle is account recovery.
The product decision sounds simple: use one passwordless email code so a player can recover progress across devices without remembering which social provider they chose. But verifying a person is not the same as knowing which game record, progression history, and earned value belong with them.
Our early model used one installation as the starting point for identity. That was enough for internal play. It is not enough to make a reliable promise about restoring everything across a reinstall or a second device.
So we stopped the recovery work and moved the ownership foundation ahead of it. During review, we also caught email data entering gameplay storage before merge and held the change until that data was removed. Authentication should hold the email. Game records should use internal identifiers. We will not invent a best guess or describe recovery as complete before the game can keep that promise safely.
This is the least visible kind of progress. It may also be the most important. A false recovery button would look better in a feature list than an architecture blocker. It would be worse for players.
What changed in the way we work
The work remains founder-led. I decide the product promise and the tradeoffs I am willing to make. Production keeps the sequence honest. Client and Server/shared engineering work in focused lanes. The Game Director reviews behavior and evidence. Analytics work keeps measurement useful without collecting more than we need. Marketing protects the line between a candid update and a premature claim.
Codex helps each of those roles carry context, draft work, run checks, and return evidence. It does not decide what Wordulate should be, and it does not get to wave a change through. Recent failures have made that distinction sharper.
I now ask three questions where one used to feel sufficient:
- Does the code behave under the failure cases we know?
- Does the actual build prove the behavior on a real or representative device?
- Has a human owner approved the next irreversible step?
The answers can be different. A simulator can prove a startup path without proving the store build. An automated test can cover conditions we should not deliberately trigger on a tester's device. A staging candidate can pass its checks while real advertising remains disabled. Keeping those statements separate is part of being honest about readiness.
Since July 18, we have built more Wordulate. We have also thrown away easy sentences about what "works."
That is the progress I trust most. Not fewer problems, and not a perfect march toward release. A shorter distance between a failure and the durable rule that keeps us from making the same mistake twice.