Skip to content

Repository files navigation

Forge — Starship Design & Dependency Explorer

Forge combines interactive 3D assembly visualization with a graph model of component relationships, so engineers can explore designs, trace dependencies, and understand the downstream impact of engineering changes.

Disclaimer — Unofficial fan/engineering project. Not affiliated with, endorsed by, or connected to SpaceX. The vehicle is a Starship-class methalox launcher assembled from entirely synthetic parts: a procedurally generated 52 m × 9 m exterior (smooth lathe ogive nose, stainless hull with construction-ring textures, asymmetric tile heat shield, four flaps on animated pivots, six engine bells) plus fictional internal propellant and avionics components. No proprietary data or CAD was used or imitated.

The model follows the asset PRD's fidelity ladder: correct silhouette first, then PBR stainless + tile-pattern heat shield via procedurally painted color/metallicRoughness/normal maps embedded in the GLB, then engineering granularity — 32 selectable components (SS_* meshes ↔ AERO-* / TPS-* / ENG-* ids) instead of thousands of fasteners. Flap-cant sliders, an assembly-explode slider and camera presets are built into the viewer.

Screenshots

Change-impact analysis — selecting the mid heat shield dims the vehicle to its dependency chain, with affected components and subsystems reported live in the inspector.

Change-impact analysis on the mid heat shield

Studio inspection — the aft left flap selected against the hexagonal tile heat shield, its flight-computer and hull links traced in the dependency graph below.

Aft flap selected in studio mode

Engine bay close-up — the ENGINES camera preset frames the Raptor Vacuum bells under the skirt while the selected engine's supply and control wiring is highlighted.

Raptor Vacuum engine bay close-up

The flagship workflow

  1. Open Forge → Starship loads in Three.js (assembly tree, search, viewer).
  2. Search V-104 → camera flies to the Methane Isolation Valve.
  3. Click it → inspector shows material/mass/revision/status/owner/manufacturing.
  4. Graph panel shows its dependency neighborhood (React Flow).
  5. Press Analyze Change Impact → Neo4j traverses ATTACHED_TO | CONNECTED_TO | DEPENDS_ON | SUPPLIES edges outward.
  6. The valve stays amber, direct dependencies glow orange, downstream components cyan, everything else fades to near-invisible.
  7. Click any impacted part → camera flies there; graph re-centers.
$ curl "localhost:5080/api/components/V-104/impact?depth=4"
{
  "componentId": "V-104",
  "directImpact": 1,
  "transitiveImpact": 10,
  "maxDistance": 4,
  "affectedSubsystems": ["Propellant System", "Raptor Propulsion"],
  ...
}

Downstream at depth 4: both manifolds feed all six engines (RAP-*), which hang off the thrust puck.

Architecture

React + TypeScript (apps/web)
├── raw Three.js viewer      physical structure
└── React Flow panel         logical structure
          │ REST
          ▼
ASP.NET Core 8 (apps/api)
├── ImportService            validation + batched graph writes
├── ImportValidator          pure, unit-tested rules (§19-style)
├── GraphRepository          every Cypher query lives here
          │ bolt
          ▼
        Neo4j 5              design graph

Why Neo4j here: change impact is a variable-depth graph traversal ((start)-[:ATTACHED_TO|CONNECTED_TO|DEPENDS_ON|SUPPLIES*1..4]->(affected)). In SQL this is recursive CTE territory with poor locality; Cypher expresses the pattern directly, and Neo4j's index-free adjacency makes each hop cheap. Conventional application data (users/projects/revisions) would live in PostgreSQL — deferred until the revision system lands.

Traversal direction (documented tradeoff)

Edges are oriented away from the changed part toward affected parts: tank SUPPLIES line SUPPLIES valve SUPPLIES manifold SUPPLIES raptor, bolt ATTACHED_TO bracket, raptor ATTACHED_TO mount. Impact follows outgoing edges only; cycles over traversal types are rejected at import time, and depth bounds guarantee termination regardless. CONTROLLED_BY / POWERED_BY point consumer→source and are shown in dependency views but deliberately excluded from impact propagation (MVP simplification).

Repository layout

apps/web                  React + TS + Vite + raw Three.js + React Flow + TanStack Query + zustand
apps/api                  ASP.NET Core 8 (Controllers / Services / Domain / Infrastructure)
apps/api/tests            xUnit — validator rules (duplicates, dangling refs, meshes, cycles)
packages/shared-types     DTO contracts shared by API consumers and the UI
data/astra-x/starship.mjs high-fidelity procedural Starship generator (zero-dep GLB + PNG writer)
data/astra-x/*.json|.glb  generated package (committed for instant demos)
infrastructure/docker     Dockerfiles, nginx.conf, docker-compose.yml

(data/astra-x is a legacy folder name from an earlier iteration; the assembly id is STARSHIP.)

Quick start (dev)

Prereqs: Node 22+, .NET 8 SDK, Docker.

npm install                                   # workspaces: web + shared-types + generator

docker compose -f infrastructure/docker-compose.yml up -d neo4j

ASPNETCORE_URLS=http://localhost:5080 dotnet run --project apps/api
# first boot waits for Neo4j, validates the package, imports the vehicle graph (~2 s)

npm run dev --workspace apps/web              # http://localhost:5173

Port 5080 (not 5000) because macOS AirPlay Receiver occupies 5000.

Full stack in Docker

docker compose -f infrastructure/docker-compose.yml --profile full up --build
# web :5173   api :5080   neo4j :7474 (browser) / :7687 (bolt)

Regenerating the dataset

npm run generate:data                  # writes vehicle.glb + *.json
node data/astra-x/generator/verify.mjs        # glTF-transform round-trip validation

Then wipe & reimport: curl -X POST localhost:5080/api/assemblies/STARSHIP/import.

API

Method Route Purpose
GET /api/assemblies/{id} summary: counts, revision, subsystems
GET /api/assemblies/{id}/tree component tree grouped by subsystem
POST /api/assemblies/{id}/import validate + (re)build the design graph
GET /api/components/{id} full metadata
GET /api/components/search?q=&take= id / name / subsystem / material / revision
GET /api/components/{id}/dependencies depth-1 neighborhood as {nodes, edges}
GET /api/components/{id}/impact?depth=4 directed traversal, clamped depth 1–8

Static: /models/vehicle.glb served by the API (model/gltf-binary).

Import validation

Rejects packages containing duplicate ids, dangling relationship endpoints, mesh references absent from the GLB, components without geometry nodes, revisions < 1, self loops, unknown relationship types, and cycles over impact-traversal edge types. Errors are reported per component (400 + report JSON); the API stays up and imports can be retried.

Graph model

Nodes: Component, Subsystem, Material, ManufacturingProcess, Revision Engineering rels: ATTACHED_TO · CONNECTED_TO · DEPENDS_ON · SUPPLIES · CONTROLLED_BY · POWERED_BY Derived rels at import: PART_OF · USES_MATERIAL · MANUFACTURED_BY · HAS_REVISION

Uniqueness constraints on Component.id, Subsystem.id, Material.id, Revision.key; index on Component.name. Mesh ↔ component linkage: each GLB node's name is the component id; raycasting resolves mesh → userData.componentId → REST → Neo4j.

Measured (MVP baseline, M-series MacBook)

Metric Value Target
Import vehicle graph (32 comps / 44 rels) + GLB serve < 1 s
Impact V-104 depth 4 (warm) ~9 ms < 500 ms
Impact cold (first hit) ~280 ms
vehicle.glb size 3.9 MB incl. 6 embedded PBR textures, 33k tris
Frontend tests / backend tests 7 / 11 passing

Rendering FPS is reported in the viewer HUD. Scaling to 10k components, instancing, LOD and caching are the next performance milestone.

Testing

dotnet test apps/api/tests/Forge.Api.Tests    # validator: 11 cases incl. cycle detection
npm run test:web                              # layout/tree pure functions: 7 cases
npm run test:e2e                              # 9 Playwright specs driving the real UI

E2E requires the live stack (compose neo4j + api) and launches its own vite dev server on :5199. Specs cover app shell, search→select→inspector wiring, impact analysis flow, graph panel switching, flap/explode sliders (asserted through the viewer's node graph), and camera presets. Integration tests against a disposable Neo4j container are the next testing milestone.

Roadmap

Revision intelligence → 10k-part performance pass with before/after numbers → STEP ingestion service → rule-based design validation ("every raptor must connect to exactly one controller") → path finding between any two components → live events via RabbitMQ/SignalR.

About

Forge — Starship-themed 3D design & dependency explorer: Three.js assembly viewer + ASP.NET Core + Neo4j change-impact analysis (synthetic dataset, not affiliated with SpaceX)

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages