@instruments/colorscope
v3.1.0
Published
Color analysis toolkit for Node.js and browser-safe subpath imports. Colorscope extracts dominant colors, names and classifies colors with OKLab/OKLCH geometry, builds 128D palette embeddings, and exposes deterministic palette analysis utilities.
Downloads
2,029
Readme
@instruments/colorscope
Color analysis toolkit for Node.js and browser-safe subpath imports. Colorscope extracts dominant colors, names and classifies colors with OKLab/OKLCH geometry, builds 128D palette embeddings, and exposes deterministic palette analysis utilities.
Install
pnpm add @instruments/colorscopesharp is an optional peer dependency: math, conversion, naming, analysis, and embedding subpaths work without it, so browser and math-only consumers skip the native install entirely. Image extraction (extraction/, border/, and the root barrel, which re-exports them) requires it — add it alongside colorscope in Node/server code:
pnpm add @instruments/colorscope sharpBreaking change (since sharp became optional): importing the root barrel without
sharpinstalled now fails at import time. Either installsharp, or switch to subpath imports (@instruments/colorscope/math,/convert,/naming, …) if you don't use extraction.
Use the root import from Node/server code, and use subpath imports from browser or React client components.
Quick Start
import { extractColorsFromUrl, withColorNames } from "@instruments/colorscope";
import { analyzePalette } from "@instruments/colorscope/analysis";
import { paletteToEmbedding } from "@instruments/colorscope/embedding";
const { colors } = await extractColorsFromUrl("https://example.com/product.jpg");
const named = withColorNames(colors);
const analysis = analyzePalette(named);
const embedding = paletteToEmbedding(named);Client-Safe Imports
import type { QuantizedColor } from "@instruments/colorscope/types";
import { analyzePalette } from "@instruments/colorscope/analysis";
import { hexToOklab } from "@instruments/colorscope/math";
import { getColorName, getColorAttributes } from "@instruments/colorscope/naming";
import { paletteToEmbedding } from "@instruments/colorscope/embedding";
import { generateHarmony } from "@instruments/colorscope/harmony";Server-only catalogue helpers live under @instruments/colorscope/naming/server because they load vendored library data from the package.
import { createColorResolver } from "@instruments/colorscope/naming";
import { getLibrary } from "@instruments/colorscope/naming/server";
const resolver = createColorResolver({
libraries: [getLibrary("core"), getLibrary("farrow-ball")].filter(Boolean),
});Published Subpaths
| Subpath | Purpose |
| ----------------------------------------- | --------------------------------------------------------------------------- |
| @instruments/colorscope | Full Node/server barrel, including extraction |
| @instruments/colorscope/extraction | Sharp-backed image color and spectrum extraction |
| @instruments/colorscope/border | Uniform border detection for product imagery |
| @instruments/colorscope/math | HSL, RGB, OKLab math and perceptual distance |
| @instruments/colorscope/convert | OKLab, OKLCH, RGB, HSL, and hex conversion |
| @instruments/colorscope/analysis | Palette temperature, vibrancy, brightness, mood, clustering, and comparison |
| @instruments/colorscope/embedding | 128D palette and region embeddings |
| @instruments/colorscope/naming | Canonical taxonomy, lexical attributes, and resolver core |
| @instruments/colorscope/naming/semantic | Hybrid lexical and semantic text resolver |
| @instruments/colorscope/naming/server | Built-in catalogue libraries for server runtimes |
| @instruments/colorscope/palette | Palette grids, anchor palettes, and distribution distance |
| @instruments/colorscope/mood | Mood presets and OKLab region helpers |
| @instruments/colorscope/sorting | Palette sorting utilities |
| @instruments/colorscope/spectrum | Client-safe OKLCH spectrum model |
| @instruments/colorscope/taxonomy | Deterministic taxonomy descriptions and rule metadata |
| @instruments/colorscope/temperature | Warm/cool and light/dark appearance shifts |
| @instruments/colorscope/tolerance | UI tolerance slider to OKLab threshold mapping |
| @instruments/colorscope/harmony | Color harmonies and tonal palettes |
| @instruments/colorscope/accessibility | WCAG contrast and color-blindness simulation |
| @instruments/colorscope/format | CSS, Tailwind, and SCSS palette exports |
| @instruments/colorscope/types | Shared TypeScript data shapes |
Embeddings
paletteToEmbedding() returns a fixed 128D L2-normalized vector. Store EMBEDDING_VERSION next to persisted vectors and rebuild indexes when it changes.
import {
EMBEDDING_VERSION,
embeddingSimilarity,
paletteToEmbedding,
} from "@instruments/colorscope/embedding";
const a = paletteToEmbedding(["#c67a5c", "#8a9e82"]);
const b = paletteToEmbedding(["#bf7458", "#809775"]);
console.log(EMBEDDING_VERSION); // "oklch-anchor-quantiles-v11"
console.log(embeddingSimilarity(a, b));Semantic Naming
Semantic color resolution uses baked openai/text-embedding-3-small concept vectors and a caller-provided encoder.
import { createHybridColorResolver } from "@instruments/colorscope/naming/semantic";
const resolver = createHybridColorResolver({
encode: (text) => embedWithYourProvider(text),
});
await resolver.resolveColorName("warm limestone");Generate the package and docs with:
pnpm --filter @instruments/colorscope build
pnpm --filter @instruments/colorscope generate:api-docs