Files
colour-tools/public/docs/ARCHITECTURE.md
T

70 lines
3.5 KiB
Markdown

# Architecture
Colour Tools is a client-only React application built as relocatable static
files. The UI and calculation engine are intentionally separated so colour
operations can be tested without a browser and UI state can keep showing the
last valid result while an input is incomplete.
## Layers
1. `src/colour/` is the serialisable colour domain. It parses and formats
colours, converts gamuts, composites layers, interpolates stops, evaluates
contrast and Delta E, simulates colour-vision deficiencies, and builds or
exports palettes. Its public API is re-exported from `src/colour/index.ts`.
2. `src/palette/` contains browser-independent raster bounds, sampling and
deterministic OKLab clustering. `src/workers/palette.worker.ts` exposes the
expensive extraction path to a dedicated worker.
3. `src/components/` contains the seven workspaces and shared accessible
controls. Workspace selection is represented by a URL fragment, so a view
can be bookmarked without router or server support.
4. `src/hooks/` owns bounded device-local UI persistence. Image bytes are not
stored there.
5. `src/toolbox/` contains the checked manifest identity. The shared Toolbox
shell supplies navigation, contextual actions and theme behaviour without
changing the standalone application domain.
## Colour values
The engine's `ColourValue` is a plain object: colour-space identifier, three
numeric coordinates and alpha. It deliberately carries coordinates that may
sit outside a display gamut. Color.js 0.7.1 supplies standards-aligned parsing
and conversion primitives; Colour Tools wraps these in typed, bounded domain
operations and stable UI formats.
Browser preview is a separate operation. It maps a value to sRGB and reports
whether mapping occurred. This keeps display limitations from mutating the
source colour used by later conversions or comparisons.
## Raster pipeline
The image picker validates the selected file before decode, rejects excessive
bytes/dimensions/pixels, then draws the decoded image to a same-origin in-memory
Canvas 2D surface. Sampling reads a bounded neighbourhood. Palette extraction
subsamples deterministically, converts points to OKLab and clusters them with a
fixed initialization and iteration bound. The worker client can fall back to
the same pure function when workers are unavailable.
Temporary object URLs are revoked and outstanding extraction is aborted when an
image is replaced or removed. No image or extracted palette is transmitted.
## Build and deployment
Vite builds with a relative base. `scripts/generate-toolbox-manifest.mjs`
checks package, application and Toolbox versions plus immutable source
identity. `scripts/prepare-release-files.mjs` places project documentation and
the exact installed runtime licence inventory beside the executable app.
The service worker is relative-scope and deployment-subpath aware. It is
progressive enhancement: the app remains usable when registration is rejected.
The deterministic packager rejects symbolic links, source maps, secret-like
filenames and root-absolute asset references before creating the release ZIP
and SHA-256 sidecar.
## Testing boundaries
Unit tests cover parsing, numerical operations, invalid inputs, raster bounds,
sampling and palette determinism. Browser smoke tests run the production build
under a restrictive policy at `/deep/nested/colour/`, exercise all major
workspaces and fail on uncaught errors or external network requests. The
Toolbox contract checker validates the static artifact independently.