# Architecture Rules Follow these rules for the whole repository. More specific `AGENTS.md` files override/add rules for their folders. ## Boundaries - `core/`: pure domain models only. See `core/AGENTS.md`. - `commands/`: the only write path for application state. - `editor/`: transient editor/app state types, e.g. viewport/camera and selection. - `renderer/`: renders the current `ImageDocument` using the graphics backend, e.g. WebGL. - `view/`: React UI shell and controls only. ## State Ownership - All persistent document state is represented by `ImageDocument` and related `core/` models. - Transient editor state is application state too: viewport/camera, selection, tools, active artboard/layer, drag state, etc. - Commands are the only code allowed to create, replace, or mutate persistent or transient state. - React must not own, manage, derive authoritative, or alter document/editor state. - React may hold only local ephemeral UI details with no app meaning, e.g. open popover, hovered button, uncontrolled input draft before command submit. - Do not update state directly from React event handlers, renderer callbacks, effects, stores, services, or keybind handlers. Dispatch a command instead. ## Commands - Every state change must be modeled as a command with an explicit id, payload, and context. - Commands must be deterministic and testable; avoid DOM, React, WebGL, timers, network, and filesystem access inside command execution. - Commands return/apply the next state; they should preserve domain invariants and validate payloads before changing state. - UI actions, menus, toolbar buttons, keybinds, and renderer interactions all request changes by dispatching commands. ## React / View - React displays current state and exposes user intent. - React components receive state snapshots/selectors and command dispatch functions; they do not contain business rules. - Do not put rendering engine logic, document mutation logic, or editor workflow ownership in React components. - Effects are for UI integration/subscription setup only, not for deriving or correcting application state. ## Renderer - The renderer draws the current `ImageDocument` plus read-only editor state overlays. - Renderer code must not mutate document/editor state directly. - Renderer interactions may emit intents/events that are translated into commands. - Keep rendering backend details isolated behind renderer APIs; do not leak WebGL objects into `core/`, `commands/`, or React state. ## Keybinds - Keybind handling is ordered and explicit. - First check the global keybind consumer/map. - If the global consumer handles the keybind, stop. - If not consumed globally, the keybind may be consumed by dispatching a command. - Keybind handlers must not mutate state directly. - Avoid ad-hoc component-local shortcuts unless they are purely local UI behavior and cannot affect app/editor/document state. ## Imports - `core/` imports nothing from app layers. - `commands/` may import `core/` and `editor/`; avoid importing React or renderer backend APIs. - `editor/` may import `core/` types; it must not import React, commands, renderer, storage, or backend APIs. - `renderer/` may import `core/` and `editor/` types; it must not import React components. - `view/` may import UI components and command dispatch interfaces; avoid importing renderer internals except through stable view-facing adapters.