I build complete games from your assets, design and specs.
Give me resources and a game design document — I'll ship a production-grade game. I own the entire code layer: client, server, data, UI logic, performance, anti-cheat. You bring the art, audio and design — I turn it into a working product.
Two columns that remove most miscommunication before we start.
Not mockups — playable builds. Open them and try the mechanics yourself.
A production idle game: economy, combat, cross-server sync — under the hood of a simple click.
Clicker is a production idle game where players level up heroes, fight monsters and go through Ascension for shards that unlock new upgrades. Complete layer separation — the client is never authoritative, the server recalculates everything itself. Two independent stores (Reflex), Broadcaster synchronization, BigNum math for numbers beyond e15, virtualized hero card lists, object pooling (damage numbers, loot, sounds, click VFX), offline progress between sessions and UI localization. Heavy calculations (“buy max” across hundreds of levels) are computed with a closed-form geometric series sum in O(log N) with a bounded cache — no level-by-level iteration, so the cost does not grow with the number of levels. MemoryStore and MessagingService power the cross-server clan leaderboard and a single clan boss (shared HP across all servers); Discord alerts go through a custom Cloudflare worker.
Architecturally: SSoT on the server, an immutable client store (Reflex), services and controllers through Flamework instead of hand-rolled singletons — event-driven, not polling every frame; async work through coroutines and event APIs, Promises used sparingly (ProfileStore and single-result network operations).
200+ files · 15+ game mechanics — the entire journey solo: from architecture to production.
No code here — the essence of the problem and the direction of the fix. Code and details on request: I will show and explain it in plain terms.
A purchase can be re-confirmed by Roblox — risk of granting the reward twice.
solutionEvery purchase is remembered by id; a repeated confirmation does not grant the reward again.
A shared cross-server boss: several servers hit the same state simultaneously.
solutionDamage is applied through an atomic update of the shared state, not separate copies per server.
A player leaves and immediately rejoins while data is still loading — risk of two processes on one profile.
solutionRejoining waits for the previous operation to finish instead of running in parallel.
A server can crash in the middle of a currency operation — risk of lost progress or duplication.
solutionOn shutdown the server waits for active saves to finish instead of cutting off instantly.
A double click or spamming one action — risk of running the operation multiple times.
solutionUntil the operation completes, a repeated identical request from the player does not start a new one.
The client cannot be trusted with price/balance — data can be tampered with when sending a request.
solutionOnly the action itself is accepted from the client; all numbers are recalculated on the server.
Clicks must feel instant, but the economy cannot tolerate desync between tabs/devices.
solutionClicks apply instantly on the client (optimistically); purchases only after server confirmation — the button is locked until a response.
Currency in an idle game quickly exceeds normal number precision (e15 and beyond) — rounding and bugs begin.
solutionAll game numbers are strings in a BigNum format with their own math engine, not built-in numbers.
A list of hundreds of hero cards in the UI lagged the game — all of them rendered at once.
solutionVirtualization: only visible cards live in memory; the rest are not created until needed.
“Buy max” iterates over hundreds of levels and can stall a frame mid-click.
solutionIteration replaced with a closed-form geometric series sum — O(log N) BigNum operations instead of hundreds of iterations, plus a hard-limited FIFO cache. The cost stops depending on the number of levels.
Naive timeout handling when loading a player profile leaked the session — the profile stayed locked.
solutionLoading is cancelled with an explicit flag, not a promise race — the profile is released on cancellation instead of staying locked.
Needed to tell a cheater with an autoclicker apart from a player with fast reactions, without punishing honest players.
solutionAction rate limits with headroom for measurement noise and a silent rejection instead of a kick, so a fast honest player is not punished for speed.
Transferring paid crystals between players across servers — a lost confirmation or redelivery can duplicate the balance.
solutionAn external operations ledger as the single commit marker: debit and credit are applied against it exactly once, not on client confirmations.
Corrupted player data could silently zero out Robux-bought crystals along with purchase history.
solutionAn independent ledger of purchase receipts: if a profile is corrupted, the donation balance, history and status are restored, not lost.
One broken mechanic should not take down the whole game — places where money or player data are at stake are explicitly tested against failures; the rest is straightforward development without over-complication.
The entire UI is written from scratch, without third-party UI kits: components reactively subscribe to a shared store and re-render only when the specific data they need changes. Below are the decisions that performance and usability demanded.
50+ UI components · 20+ game-logic hooks · responsive for mobile, desktop and gamepad.
The HP bar renders every frame, the boss timer counter once a second. Driving that through React state means a subtree re-render on every tick, when only one element’s width and a piece of text change.
solutionElements keep refs and values are written directly outside React: the HP bar on Heartbeat, the timer with a 0.25s tick. Before writing, the tick compares the new value with the previous one and skips unchanged ticks. The HP bar additionally extrapolates damage between store ticks by DPS — the bar melts smoothly instead of jumping.
A component subscribing to the entire state — the UI re-renders on any change in the game.
solutionEach component subscribes to a specific value, and composite data (hero stats, purchase cost) is memoized and recomputed only when its inputs change.
One UI layout for mobile and desktop: on phones panels cover the game, on PC there are empty edges.
solutionDifferent interface trees for mobile and desktop modes, and size-dependent modals only mount after the engine reports the real screen size and topbar inset — otherwise they open with broken geometry.
Scrolling lists with item borders: the first card hits the clipping boundary and its border is cut; the scrollbar eats width.
solutionWindow and canvas geometry of a scroll are explicitly separated: each scroll has a single inset owner, both states (with and without the scrollbar) are checked, and edge elements get a stroke-safe inset.
Tooltips inside cards get clipped by list and virtualization bounds — the card disappears, the tooltip with it.
solutionTooltips render through a portal above the whole UI, anchored to the card’s real on-screen position, not its place in the list.
Concrete defensive solutions from the code. Under the spoilers — a simplified illustration of the principle, not the production code.
All alerts (donation operations, DataStore errors, bug reports) go through one WebhookService with a priority queue (donations before datastore and bugs) and batches to respect Discord limits — instead of scattered send points. Production is visible in real time without digging through logs.
webhookService.reportDataStore("save", "player X", "failed"); // datastore channel
webhookService.notify(channel, { title, description, color }); // single queue
Every action broadcast between client and server is checked against a strict schema: if an argument’s type does not match what is expected, the action is rejected entirely rather than executed with shifted values. It is also verified that an action applies only to the player it belongs to — it cannot land on someone else’s client.
const contract = { amount: "number" };
if (typeof(actual) !== contract.amount) return; // rejected outright
if (owner !== player) return; // foreign data never passes on
The monster generator is based on a seed from the zone: the same server after a restart always produces the same monster, with no need to store its model in player data.
const seed = stableHash(zone); const rng = new SeededRandom(seed); // same monster for the same input
The “player left” event in Roblox can fire before the profile save actually completes. The logic waits for the save to finish, not the leave itself — otherwise a new session could start on top of an unsaved old one.
// Before releasing the profile, always force-sync the data from the store, // then wait for the actual completion of the write — not the “left” event; // the event can arrive before the save has actually persisted. profile.Data = MainStore.getState().players[userId]!; // force-sync: data from the store releaseAndAwait(); // waited for the write to complete, not the “left” event
The kill reward is applied only after the next step has successfully started (for example, the next monster has spawned). If anything fails along the way — no reward is granted, and a repeated client packet cannot double the reward.
const ok = spawnNextMonster(); // the next step first if (!ok) return; // error — no commit, a client retry cannot double it grantReward(); // the reward only when everything above succeeded
Internal big-number normalization loops are iteration-bounded with an explicit warning rather than left unbounded — otherwise, in a rare edge case, they could cause a hang instead of just a wrong result.
let guard = 0;
while (cond) {
...
guard++;
if (guard > 3) { warn("anomalous input"); break; }
}
A procedurally generated voxel world, built to answer one question: how far can a Roblox world be pushed before the engine pushes back.
The world is a deterministic generator (seed + coordinate) plus a sparse diff of player edits — nothing about the world is persisted, it lives in RAM and replicates as compact deltas. A custom greedy + incremental mesher works directly on a raw byte buffer, distance LOD stitches chunk seams against neighbor render representations, and block parts come from an object pool instead of being created and destroyed. Explosions are volumes, not per-block lists: a sphere descriptor travels as ~20 bytes and is rasterized with the exact same predicate on client and server. Performance is measured by a custom metrics layer shared by client and server: a single registry of counters, gauges, histograms and events with a named catalog, heavy scans deferred to a sampler that runs only on dump, and one-line snapshots built to be diffed between runs — counters as absolute + window delta, timings as p50/p95/max instead of a mean that hides spikes. The server dumps the registry and the client feeds an in-game diagnostics HUD.
Architecturally: server-authoritative state, the client sends intents only, Reflex stores for player data, Flamework for services and controllers, ProfileStore for persistence. The hot path here is buffers, not objects.
buffer-first world · deterministic generation · LOD + greedy meshing · volume explosions — solo, in progress.
I map the economy, the data and the ways it can break before writing any gameplay.
In practice: where money could leak or duplicate is decided here, not after launch.
I build the mechanics and the interface to your layouts, responsive for mobile, PC and gamepad.
In practice: UI written from scratch and wired to the store — no UI kits, no per-frame re-renders.
I keep the truth on the server and validate everything the client sends.
In practice: the client sends intents only; rate limits drop spam silently instead of kicking.
I profile the build and fix the real bottleneck.
In practice: frame time, memory and load come from the profiler and the metrics layer, not guesses.
The patterns I actually use: separating server and client state (server as the single source of truth), broadcaster-based sync instead of polling, optimistic and pessimistic UI updates, BigNum math beyond float precision, virtualization of heavy lists, object pooling, throttled autosave, cancellation patterns for async operations, rate limiting and server-side validation. This is not a checklist of buzzwords — every item is here because I actually ran into it and worked out the right fix.
I work through tickets: a task description in any tracker (or just a list) — done, reported.
Happy to do a paid test task.
I can show code examples, architecture and walk through the logic of my decisions in detail.
Payment: Crypto / Robux. Other options discussed individually.
Async schedule: I work without fixed hours during the day, focused on task deadlines.
Revenue share only (a percentage of future profit). A share of project income is discussed individually only as a bonus on top of the base payment.