Deconstructing the Monolith

Modular assets and JSON-driven scene assembly.

Posted by Scott Grocott on March 27, 2026

Until now, the Metal Throne hub existed as a single, massive .glb file. While great for visualization, a monolithic model is a nightmare for gameplay. You can't easily animate a single tank, you can't calculate per-building collisions, and the browser has to render the whole thing at once. Today, I broke the monolith.

The 0,0,0 Workflow

In Blender, I isolated every building, fuel tank, and green pathway. To make them modular, I moved each individual object to the world origin (0,0,0) before exporting. This ensures that when they are loaded into A-Frame, their "pivot point" is exactly where I expect it to be.

To keep the alignment perfect, I kept the original "all-in-one" model in the A-Frame scene as a ghosted guide. I placed each modular piece directly over its counterpart in the guide, recording the exact Position, Rotation, and Scale coordinates.

The Scene Metadata (JSON)

Rather than hard-coding dozens of <a-entity> tags into my HTML, I moved all that coordinate data into a structured JSON file. This allows me to swap models, update positions, or add animation metadata without ever touching the core scene code.

{
  "assets": [
    {
      "item": "Silo_Alpha",
      "src": "./assets/silo_v1.glb",
      "pos": {"x": 12.5, "y": 0, "z": -45.2},
      "rot": {"x": 0, "y": 90, "z": 0},
      "scale": {"x": 1, "y": 1, "z": 1},
      "animation": "idle_smoke"
    }
  ]
}

The Scene Builder Component

To breathe life into this data, I wrote a custom A-Frame component called scene-loader. This script fetches the JSON file, iterates through the array, and dynamically creates the entities in the world. This is the foundation of our world-building engine.

AFRAME.registerComponent('scene-loader', {
  schema: { url: { type: 'string' } },
  init: function () {
    fetch(this.data.url)
      .then(response => response.json())
      .then(data => {
        data.assets.forEach(obj => {
          let el = document.createElement('a-entity');
          el.setAttribute('gltf-model', obj.src);
          el.setAttribute('position', obj.pos);
          el.setAttribute('rotation', obj.rot);
          el.setAttribute('scale', obj.scale);
          this.el.appendChild(el);
        });
      });
  }
});
"By separating the data from the display, the Metal Throne is no longer just a model—it's a database-driven world."

What this unlocks

Now that every building is its own entity, the possibilities have exploded. I can now give each silo its own health bar, trigger individual destruction animations, or have AI drones patrol specific coordinates pulled from the metadata.

The layout is now flexible. The world is now getting smarter.

Technical breakdown by Scott Grocott · Tools used: Blender, JSON, A-Frame JS