← Back to selected work
06/Realtime Systems/2025

3D Studio

A creation tool where non-programmers build 3D worlds with visual scripting and play them together in real time, at 10 million users. Editor, authoritative server, and the schema between them live in one repository — with sandboxed user scripts, server-side physics, and an assistant that answers in the studio's own API rather than in generic JavaScript. I also shipped several web games on top of the platform, together passing a million plays.

Role
Engineer — studio & realtime runtime
Domain
Creation tools for young makers
Reach
10M+ total users
Games shipped
1M+ combined plays
Runtime
Three.js · Ammo physics · Colyseus
Deploy
Kubernetes · Helm · ECR, 3 environments
Status
Shipped

Outcomes

10M+
TOTAL PLATFORM USERS
1M+
PLAYS ON GAMES I BUILT
SERVER
AUTHORITATIVE PHYSICS
3
ENVIRONMENTS, ROLLING DEPLOY
01 — The brief

What was
broken

The problem as it actually presented itself, and the constraints that shaped every decision after it.

Browser 3D tooling forces a choice between a rendering library with no authoring story and a heavyweight editor that ships megabytes to every player. Neither works for a product whose users are learning to build and whose players are on school laptops.

Multiplayer makes it harder. If physics runs on each client, positions disagree and someone is always wrong. If user scripts run unsandboxed, one creator's infinite loop takes down everyone in the room.

And the users asking 'how do I make the door open when the player touches it' are not going to read API documentation. The help had to answer in the studio's own vocabulary, inside the studio.

02 — Stack

What it
runs on

Models, retrieval, serving, and the operational layer that keeps it honest in production.

01Editor
  • Three.js
  • enable3d / Ammo
  • Blockly
  • Ace + acorn
02Multiplayer
  • Colyseus rooms
  • Server-side Ammo
  • Shared schema package
03Assistant
  • Threaded chat
  • Studio-API answers
  • Syntax-highlighted output
04Platform
  • Agora voice/video
  • vm2 sandbox
  • Helm + ECR rolling deploys
03 — Architecture

How it
works

The pipeline end to end — each stage, and why it earns its place in the latency budget.

  1. 01

    One schema, both sides

    Editor and server both consume a shared package that defines scene and room state, so client and server can never drift into two definitions of the same world. Serialization uses a compressed JSON format to keep scene payloads small over the wire.

  2. 02

    Browser editor

    Three.js rendering with enable3d wrapping Ammo physics, an asset library, a property panel, and Blockly for block-based scripting — with a code escape hatch for users who outgrow blocks, parsed and formatted so the transition is not a cliff.

  3. 03

    Authoritative multiplayer

    Colyseus rooms run the same Ammo physics on Node, so collisions and positions resolve server-side and clients render a state they do not get to argue with. Load tests live alongside the room code rather than in someone's local scratch directory.

  4. 04

    Sandboxed user scripts

    Creator-written script runs inside a sandbox, parsed and rewritten through an AST before it executes. A user's mistake is contained to their own logic instead of taking down the room it is running in.

  5. 05

    In-editor assistant

    A threaded assistant — one conversation thread per user — answers in the studio's own scripting API, with syntax-highlighted, copy-ready code blocks and a documentation tab beside it. It answers the question the user actually asked, in the vocabulary of the tool they are holding.

  6. 06

    Ship pipeline

    A single deploy script builds images, pushes them to the registry, publishes Helm charts, and rolling-updates the target namespace across development, staging, and production. Any subset of services can ship independently.

04 — Tradeoffs

Decisions
and their cost

Every choice below bought something and gave something up. The second half is the part worth reading.

Server-authoritative physics

Running Ammo on Node costs server CPU and adds a round trip to every interaction. Client-authoritative physics costs correctness, and in a shared world correctness is the product. The latency is hidden with interpolation; disagreement cannot be hidden at all.

Blocks with a code escape hatch

Blockly alone caps what advanced users can express; raw code alone loses beginners at the first semicolon. Supporting both means maintaining two authoring paths, and it is the only version where a user can grow inside the tool instead of leaving it.

Sandbox every user script

Sandboxed execution with AST-level parsing is slower than running code directly and it is non-negotiable when one creator's script executes in a room full of other people's sessions.

Assistant scoped to the studio's own API

A general coding assistant answers in generic JavaScript that does not exist in this engine — confidently, and uselessly. Scoping it to the studio's API and documentation made it narrower and made its answers actually runnable.

05 — Evaluation

How it was
measured

Nothing shipped on intuition. Each number below is produced by a repeatable harness that gates deploys.

Platform reach
10M+ users

Total users on the studio platform.

Games I shipped
1M+ plays

Several web games built on the platform, combined play count.

Physics authority
Server-side

Ammo runs on Node inside the room; clients render resolved state.

State definitions
1

Shared schema package consumed by both editor and server.

Script isolation
Sandboxed

AST-parsed and executed in isolation from the room runtime.

Authoring paths
2

Visual blocks and raw code, over the same underlying scene API.

Deploy targets
3 environments

Rolling updates per service across dev, staging, and production.

Load testing
In-repo

Room load tests versioned alongside the multiplayer server.

06 — Production

Guardrails
and safety

What stands between a good demo and something you can leave running unattended.

  • User scripts execute in a sandbox with AST-level parsing, isolated from the room runtime and from other players' sessions.

  • Physics and state are resolved server-side, so a modified or lagging client cannot rewrite the shared world.

  • The shared schema package makes client/server state drift a compile-time problem rather than a runtime mystery.

  • Deploys are rolling updates per service, so a bad build degrades one component instead of taking down a live room.

  • Room load tests are versioned with the server code and run before capacity changes.

  • The in-editor assistant answers within the studio's documented API surface — it suggests, it does not mutate the scene directly.

07 — Retrospective

What I'd
carry forward

The parts that generalise — earned the expensive way, on this build.

01

In a shared world, authority is the architecture. Every question about lag, cheating, or desync resolves back to who is allowed to be right.

02

Give people a ladder, not a wall. Blocks with a code escape hatch let users grow inside the tool instead of hitting a ceiling and leaving.

03

Scope an assistant to your API. Narrow and correct beats broad and plausible, especially when the user cannot tell the difference until they run it.

04

Sandboxing is not optional the moment other people's sessions are in the blast radius.