Hi there 👋

Full-cycle Roblox Developer

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.

open to projects
I take full ownership of the code layer — from architecture to production runtime Text only — task discussion, status updates, questions, feedback — no calls or voice chats. I reply fast and never disappear.
My projects
Scope

What I do — and what I don't

Two columns that remove most miscommunication before we start.

I do

  • Full game code from assets and specs
  • Client + server + networking
  • Data, saving, profile systems
  • UI logic and integration (Mobile / PC / Console)
  • Anti-cheat, anti-dupe, server-side validation
  • Optimization, profiling, runtime debugging
  • Admin tools and dev console

I don't

  • Art, 3D models, animations, VFX
  • Music and sound
  • Game design from zero (I implement your design doc)
Live games & tech demos

Real projects you can open in Roblox right now

Not mockups — playable builds. Open them and try the mechanics yourself.

—playing —visits —

Infinity Clicker

A production idle game: economy, combat, cross-server sync — under the hood of a simple click.

🛠 The game ships with a live DEV panel — every mechanic can be tested in-game: gold, shards, crystals and fragments grants; maxed heroes, upgrades, shard perks and skills; artifacts; resonance; sages and instant completion of all missions; zone teleports. Open the DEV tab in the game menu and try it all yourself.
Architecture and technical design

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.

roblox-ts TypeScript Luau Flamework Reflex React ProfileStore Sift MemoryStore MessagingService
Production failure points I closed (14 cases)

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.

problem

A purchase can be re-confirmed by Roblox — risk of granting the reward twice.

solution

Every purchase is remembered by id; a repeated confirmation does not grant the reward again.

problem

A shared cross-server boss: several servers hit the same state simultaneously.

solution

Damage is applied through an atomic update of the shared state, not separate copies per server.

problem

A player leaves and immediately rejoins while data is still loading — risk of two processes on one profile.

solution

Rejoining waits for the previous operation to finish instead of running in parallel.

problem

A server can crash in the middle of a currency operation — risk of lost progress or duplication.

solution

On shutdown the server waits for active saves to finish instead of cutting off instantly.

problem

A double click or spamming one action — risk of running the operation multiple times.

solution

Until the operation completes, a repeated identical request from the player does not start a new one.

problem

The client cannot be trusted with price/balance — data can be tampered with when sending a request.

solution

Only the action itself is accepted from the client; all numbers are recalculated on the server.

problem

Clicks must feel instant, but the economy cannot tolerate desync between tabs/devices.

solution

Clicks apply instantly on the client (optimistically); purchases only after server confirmation — the button is locked until a response.

problem

Currency in an idle game quickly exceeds normal number precision (e15 and beyond) — rounding and bugs begin.

solution

All game numbers are strings in a BigNum format with their own math engine, not built-in numbers.

problem

A list of hundreds of hero cards in the UI lagged the game — all of them rendered at once.

solution

Virtualization: only visible cards live in memory; the rest are not created until needed.

problem

“Buy max” iterates over hundreds of levels and can stall a frame mid-click.

solution

Iteration 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.

problem

Naive timeout handling when loading a player profile leaked the session — the profile stayed locked.

solution

Loading is cancelled with an explicit flag, not a promise race — the profile is released on cancellation instead of staying locked.

problem

Needed to tell a cheater with an autoclicker apart from a player with fast reactions, without punishing honest players.

solution

Action 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.

problem

Transferring paid crystals between players across servers — a lost confirmation or redelivery can duplicate the balance.

solution

An external operations ledger as the single commit marker: debit and credit are applied against it exactly once, not on client confirmations.

problem

Corrupted player data could silently zero out Robux-bought crystals along with purchase history.

solution

An 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.

UI/UX — engineering decisions (5 cases)

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.

problem

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.

solution

Elements 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.

problem

A component subscribing to the entire state — the UI re-renders on any change in the game.

solution

Each component subscribes to a specific value, and composite data (hero stats, purchase cost) is memoized and recomputed only when its inputs change.

problem

One UI layout for mobile and desktop: on phones panels cover the game, on PC there are empty edges.

solution

Different 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.

problem

Scrolling lists with item borders: the first card hits the clipping boundary and its border is cut; the scrollbar eats width.

solution

Window 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.

problem

Tooltips inside cards get clipped by list and virtualization bounds — the card disappears, the tooltip with it.

solution

Tooltips render through a portal above the whole UI, anchored to the card’s real on-screen position, not its place in the list.

Deeper: code and defensive patterns

Concrete defensive solutions from the code. Under the spoilers — a simplified illustration of the principle, not the production code.

A single Discord webhook queue

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.

Illustration
webhookService.reportDataStore("save", "player X", "failed"); // datastore channel
webhookService.notify(channel, { title, description, color });        // single queue
A contract for sync arguments

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.

Illustration
const contract = { amount: "number" };
if (typeof(actual) !== contract.amount) return; // rejected outright
if (owner !== player) return;                    // foreign data never passes on
A deterministic zone monster

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.

Illustration
const seed = stableHash(zone);
const rng = new SeededRandom(seed); // same monster for the same input
Waiting for the save to finish, not the leave event

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.

Illustration
// 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
Committing the reward at the end of the action chain

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.

Illustration
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
Guarding BigNum against stalling on anomalous data

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.

Illustration
let guard = 0;
while (cond) {
  ...
  guard++;
  if (guard > 3) { warn("anomalous input"); break; }
}
—playing —visits —

Mining — voxel tech demo

A procedurally generated voxel world, built to answer one question: how far can a Roblox world be pushed before the engine pushes back.

⛏️ In development, but playable. The world generator, chunk meshing, destruction and in-game tools (placeable torches, thrown bombs, rangefinder, world reset) are already in.
What is under the hood

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.

roblox-ts TypeScript Luau Flamework Reflex React ProfileStore Sift buffer
Process

How I work

01

Architecture & data

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.

02

Gameplay & UI

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.

03

Networking & anti-cheat

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.

04

Optimization & polish

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.

Approach

How I approach a task

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.

Terms

How to work with me most conveniently

yes

I work through tickets: a task description in any tracker (or just a list) — done, reported.

yes

Happy to do a paid test task.

yes

I can show code examples, architecture and walk through the logic of my decisions in detail.

yes

Payment: Crypto / Robux. Other options discussed individually.

yes

Async schedule: I work without fixed hours during the day, focused on task deadlines.

no

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.

Contact

Have assets and a design doc?

Send me the scope — I'll tell you what's realistic and how long it takes. Text only, no calls.