Direct Light Architecture

September 5, 2026 · View on GitHub

This is the short current architecture map. The full historical architecture notes are archived at docs/history/snapshots/ARCHITECTURE_FULL_2026-06-29.md.

Entry Points

  • src/main.tsx mounts React.
  • src/App.tsx stays thin and renders DirectLightApp.
  • src/app/DirectLightApp.tsx and src/app/AppShell.tsx compose the app shell.
  • showcase/ contains the GitHub Pages project page and is separate from the main app source.

Directory Boundaries

  • src/app — app shell, stage layout, view badges, A/B compare containers.
  • src/scene — Three.js / React Three Fiber rendering, camera rigs, drag controllers, 3D objects.
  • src/ui — panels, object list, top bar, controls, export UI.
  • src/ui/onboarding — first-run tour state/context, target positioning, focus handling, and replay entry; preference persistence stays outside scene data.
  • src/state — Zustand store, store types, action factories.
  • src/state/actions — all state mutation logic.
  • src/domain — product/domain pure logic.
  • src/data — stable presets, specs, default scene data.
  • src/i18n — in-repo typed localization layer.
  • src/lib — generic helpers.
  • showcase — static GitHub Pages showcase page only.

Rules

  • Keep src/App.tsx, src/main.tsx, and app shell files thin.
  • Do not put action logic back into src/state/store.ts.
  • Do not put Three.js rendering code into UI panels.
  • Do not put UI form logic into scene components.
  • Do not add language fields to scene data, saved presets, snapshots, custom fixtures, or fixture packs.
  • Do not mutate built-in data tables for display-language changes; use display helpers keyed by id.
  • Do not modify main app code under src/ for showcase-only work.

Current Stable Modules

  • User-customizable figure models: src/data/personModels.ts, src/scene/PersonGLB.tsx.
  • Studio drag bounds: src/domain/studioBounds.ts, used by GroundDragController.
  • Shadow mode / normal bias: src/scene/StudioScene.tsx, src/scene/LightRig.tsx, src/ui/StudioPanel.tsx.
  • Custom fixtures: src/domain/customFixtures.ts, src/domain/customFixturePack.ts, src/state/actions/fixtureActions.ts.
  • Localization: src/i18n/*, src/i18n/display.ts, message dictionaries under src/i18n/messages.
  • First-run guidance: src/ui/onboarding/*, src/i18n/messages/onboarding.ts, and the independent direct-light.onboarding.v1 preference in src/lib/storage.ts.
  • Local persistence: src/lib/storage.ts returns write success; preset / fixture actions commit Zustand state only after a successful localStorage write, while UI modules own localized failure feedback.
  • Production chunking: vite.config.ts uses Vite 8 rolldownOptions.output.codeSplitting groups with explicit max sizes; do not replace this by increasing chunkSizeWarningLimit.

Lighting-plan exchange (web / main, 2026-09-05)

  • src/domain/lightingPlan.ts owns the versioned envelope, validation, top-view SVG and printable HTML. Embedded scene data remains SceneConfig; language is passed to the report renderer, not saved into scene data.
  • src/ui/LightingPlanActions.tsx owns camera-view capture, local download/file selection and feedback. It reads only inert JSON from an imported HTML file.
  • src/state/actions/presetActions.ts owns additive preset/fixture persistence. Imported fixture IDs are remapped; the active scene is not replaced. Preview images remain in the exported HTML and do not inflate preset storage.

Documentation Note

Changed in the 2026-06-29 cleanup: this root architecture doc was shortened to current boundaries and rules.

Not changed: code structure, module responsibilities, runtime behavior, build behavior, or release status.

Changed on 2026-07-10: documented the new UI-owned onboarding module and its app-preference boundary. Not changed by that note: scene/state schemas, rendering ownership, action boundaries, or release status.