Files
webeditor3d/CHAT_CONTEXT.md

6.2 KiB

CHAT_CONTEXT.md

This file is the lightweight startup context for new Codex chats.

Read this after AGENTS.md. Then inspect only the relevant sections of architecture.md, roadmap.md, and testing.md for the active slice.

This file does not replace the full docs. It exists to keep new chats focused and to reduce repeated context load.


Product summary

This repo is a browser-based 3D scene authoring tool with a built-in runner.

Core loop:

  1. author a scene
  2. save/load it reliably
  3. run it in-browser immediately

The product prioritizes:

  • intuitive whiteboxing / level blocking for interactive 3D environments
  • imported assets as first-class additions
  • typed entities and simple interactions
  • browser-native delivery

It is not:

  • an unlimited general-purpose engine platform
  • a Blender replacement
  • a general CAD tool
  • an R3F showcase

Hard architectural rules

  • The canonical SceneDocument is the source of truth.
  • The document must stay independent from three.js objects.
  • Editor-authored mutations should flow through commands.
  • The editor viewport is derived from the document.
  • The runner is a sibling system, not an editor hack.
  • Canonical document format is project JSON, not glTF/GLB.
  • Portable save/load for asset-bearing scenes should use a project package built around that JSON.
  • Runner/deployment output is downstream from the document/runtime build and is separate from editable project save/load.
  • Model instances are separate from typed entities.

Early binding decisions

These are fixed for the early milestones unless a later slice explicitly changes them.

Coordinates and units

  • world is right-handed and Y-up
  • +X is right
  • +Y is up
  • units are meter-like

Repo shape

  • keep the repo as a single Vite app
  • keep domain folders under src/
  • do not split into a monorepo early

State ownership

  • do not use the React tree as the canonical state container
  • keep canonical state in a thin external editor store/service

Persistence

  • version the document from day one
  • keep migrations explicit
  • early project persistence can be local draft storage plus JSON import/export
  • once binary assets exist, portable save/load should use a project package such as scene.json plus bundled assets
  • canonical JSON stays the source document format underneath that project package
  • runner package output is a separate deployable artifact
  • binary assets must survive reload via embedded or project-scoped persistent storage
  • never rely on Blob URLs as the only persisted asset reference

Current box-solid foundation

  • early slices began with an axis-aligned box shape and stable face IDs
  • stable box face IDs are:
    • posX
    • negX
    • posY
    • negY
    • posZ
    • negZ
  • posY is top and negY is bottom

Whitebox direction

  • move away from grid-bound brush thinking toward whitebox solids
  • allow floating point transforms
  • allow free object rotation
  • use the grid as optional snap/reference help, not as a hard restriction
  • unify object / face / edge / vertex editing around one transform-driven interaction model
  • non-planar quads are acceptable if triangulated deterministically in derived geometry
  • non-convex whitebox solids are acceptable if the solid mesh/collider pipeline can support them

Early UV data

Per face, keep explicit UV transform values such as:

  • offset
  • scale
  • rotationQuarterTurns
  • flipU
  • flipV

“Fit to face” should rewrite explicit values, not add a magical persistent flag.

Model placement

  • imported assets live in the asset registry
  • placed imported models live in modelInstances
  • typed scene objects like PlayerStart, TriggerVolume, or lights live in entities
  • collision authoring for imported models belongs on modelInstances, not asset records
  • generated imported-model collider data should be derived from asset geometry + instance transform + authored settings
  • for imported-model collider types beyond simple boxes, prefer a Rapier-backed collision/query layer over extending the handcrafted collision code indefinitely
  • broad-phase and narrow-phase pruning should come from that collision/query layer, not custom app code

Interaction scope

  • keep Trigger -> Action -> Target typed and explicit
  • do not add actions for systems that do not exist yet

World environment vs local lights

  • global background / ambient / sun / fog belong in world settings
  • local authored lights belong in typed entity schemas
  • true skyboxes or environment textures belong after persistent asset storage exists

What a good slice looks like

Each slice should land the smallest coherent end-to-end version of the feature across the layers it touches:

  • document data
  • commands
  • viewport behavior
  • runner behavior if relevant
  • persistence
  • UI
  • tests

Do not land speculative scaffolding with no immediate slice use.

If a roadmap item is too large, split it into smaller vertical slices.


Required habits for implementation

  • Inspect the current repo first.
  • Extend the current implementation instead of restarting architecture.
  • If persisted schema changes, update versioning/migrations and add a compatibility test.
  • Run the narrowest relevant checks you can.
  • Report what was actually verified.

Early slice ordering to keep in mind

  • M0: foundation, document, commands, persistence, test setup
  • M1: axis-aligned box brushes, face materials/UVs, runner, first-room polish, world lighting basics
  • M2: typed entities, simple trigger/action/target interactions, click interactions
  • M3: GLB/GLTF import, local lights + skyboxes, animation, spatial audio
  • M4+: whitebox-solid interaction model, component editing, derived solid triangulation/collision

That ordering matters because:

  • world settings do not need entity or asset pipelines
  • local lights need the entity system
  • skyboxes need persistent asset storage
  • animation and audio actions should land only with those runtime systems

When to open the full docs

Open the relevant full sections when:

  • persistence schema changes
  • runtime/editor boundaries are being touched
  • a slice adds new tests or new failure modes
  • geometry semantics are non-trivial
  • import/export behavior changes

Otherwise, stay focused on the active slice and keep the implementation small.