Palette Library Developer Reference
A source-level map of library/palette/index.html and
library/palette/palette-library.js: virtual data, deterministic generation, state,
rendering, exports, sharing, saved items, UI chrome and validation.
Overview
A source-level map of library/palette/index.html and library/palette/palette-library.js : virtual data, deterministic generation, state, rendering, exports, sharing, saved items, UI chrome and validation.
1. Runtime overview
+Palette Library is a static page plus an ESM browser runtime. The page shell declares SEO, structured data, application containers, filters, tabs and shared Auric Artisan UI chrome. The runtime fetches a compact deterministic manifest, materializes only needed palettes, enriches them with color science data and powers the Inspect, Harmony, Accessibility, Stats, Export and Saved workflows.
- Page shell:
library/palette/index.html. - Runtime:
library/palette/palette-library.js. - Data URL:
/data/palette-db/palettes.json. - Saved key:
aa.palette.saved. - Analysis sample: up to 2,000 palettes (
ANALYSIS). - Share type:
palette. - Workspace domain:
palette.
2. File and dependency map
+| File | Role |
|---|---|
library/palette/index.html |
HTML route, SEO, JSON-LD, application containers, tabs, filters and includes. |
library/palette/palette-library.js |
ESM runtime for virtual palette generation, filtering, rendering, inspection, export, save and share. |
data/palette-db/palettes.json |
Compact deterministic manifest for 5,000,000 palettes. |
js/library/page-mirror.js |
Mirrors saved palettes into the Library workspace. |
js/library/share/dialog.js |
Opens the share dialog for palette payloads. |
js/library/share/router.js |
Registers the palette share handler and hydrates shared palette ids.
|
js/library/tokens/dialog.js |
Opens the design-token export dialog. |
js/library/tokens/index.js |
Provides tokensFromSwatchList() for selected-palette token output. |
/js/unified.js |
Shared site behavior for includes, legal sections, cursor, loader and page chrome. |
3. Page shell, SEO and UI Chrome
+The page shell is an indexable route with application markup in the initial HTML. It preloads the palette manifest and describes the collection with structured data.
- Canonical:
https://auricartisan.com/library/palette/. - Preload:
/data/palette-db/palettes.json. - Structured data: ImageObject, CollectionPage and BreadcrumbList.
- Shared styles: main, unified, dark-mode and palette-library CSS.
- Chrome: header, time, announcement, custom cursor, scroll rail, loader, eye-rest panel, footer, idle layer and generated inline scripts.
- Application panels: Library, Inspect, Harmony, Accessibility, Stats, Export and Saved.
Keep this route visually aligned with other Auric Artisan library pages. The docs should cover the page chrome because users experience the palette browser as part of the larger library system, not as an isolated script.
4. DOM contract
+
palette-library.js resolves fixed ids on load. Rename these only with matching
runtime updates.
| Group | Important IDs |
|---|---|
| Masthead | plib-title, plib-hero-count,
plib-browse-title |
| Search | plib-search, plib-result-search,
plib-result-clear, plib-shuffle,
plib-random |
| Tabs and panels | .anz-tab-btn, .anz-panel, p-library,
p-inspect, p-harmony, p-accessibility,
p-stats, p-export, p-saved |
| Filters | plib-filter-hue, plib-filter-chroma,
plib-filter-light, plib-filter-method,
plib-sort, plib-reset, plib-export-visible |
| Library grid | plib-loading, plib-grid,
plib-tab-library-badge, plib-page-info,
plib-scroll-top, plib-tab-saved-badge |
| Advanced content | plib-inspect-empty, plib-inspect,
plib-harmony, plib-accessibility,
plib-stats, plib-export, plib-saved,
plib-toast |
5. Manifest contract
+
loadData() fetches DATA_URL with cache: "force-cache".
The runtime rejects expanded palette arrays because this public page is designed for compact
deterministic data.
{
"schema": "aa.palette-db.compact.v1",
"format": "deterministic-palette-gen-manifest",
"source": "@auric-artisan/palette-gen",
"generated_at": "2026-05-14T13:16:34.297Z",
"count": 5000000,
"colors_per_palette": 5,
"seed": 42,
"batch_size": 50000,
"batch_seed_stride": 2654435761,
"methods": [
"complementary",
"triadic",
"analogous",
"tetradic",
"golden_ratio",
"random",
"monochromatic"
]
}
The loader normalizes missing fields with fallbacks, but production data should keep the manifest explicit. Method filtering, random generation and share-link hydration all depend on the manifest staying stable.
6. Virtual Palette Generation
+The runtime materializes palettes deterministically. This is the core of the 5,000,000-palette viewer.
nextXor()advances a xorshift integer state.batchSeed(batch)computesseed + batch * batch_seed_stride.paletteId(index)returnspal_plus the base-36 index.indexFromPaletteId(id)acceptspal_...ids or numeric strings.methodForIndex(index)assigns a method from the deterministic seed and local index.generateRange(startIndex, count)skips xorshift values to the target local index, then generates RGB triples for each palette.enrichPalette(index, rawColors)computes HEX, RGB, Lab, OKLCH, contrast, Delta E average, entropy and contrast matrix.
The cache stores up to 1,200 materialized palettes in state.paletteCache. That
keeps repeated inspection, saved palettes and nearby rows fast without retaining the whole
corpus.
7. State and load sequence
+
The runtime uses a module-local state object for manifest, analysis sample,
selection, cache and panel state, plus scan and direct objects for the grid.
{
dataset: null,
count: 0,
filteredCount: 0,
visiblePalettes: [],
analysisScanned: 0,
activePalette: null,
exactSearchIndex: null,
paletteCache: new Map(),
panelsRendered: {
harmony: false,
stats: false,
accessibility: false,
export: false,
saved: false
},
progress: {
browse: false,
inspect: false,
harmony: false,
accessibility: false,
export: false
}
}
- Resolve DOM ids into
els. - Attach event listeners for search, filters, cards, exports, tabs and the back-to-top button.
- Call
loadData(). - Fetch and normalize the deterministic manifest.
- Populate method filter options.
- Build the analysis sample and give the virtual grid its source.
- Render saved panel state and register the
paletteshare handler.
8. Color science helpers
+rgbToHex()serializes generated RGB triples.rgbToLab()computes CIE Lab values for inspection and Delta E average.rgbToOklab()andrgbToOklch()compute perceptual lightness, chroma and hue.contrastRatio()computes WCAG-style contrast between colors.dominantHue()computes weighted hue from OKLCH chroma.hueSpread()computes the largest circular hue distance in a palette.minPairContrast()andmaxPairContrast()summarize internal palette contrast.deltaEAvg()averages pairwise Lab distance.paletteEntropy()bins OKLCH hue into ten buckets.harmonyLabel()returns Neutral, Diverse, Triadic, Analogous or Monochrome.
These helpers are runtime-facing approximations for browsing and triage. Keep docs and tests in sync if thresholds or formulas change, because filters and panel labels will change.
9. Filtering, sorting and scrolling
+Palette Library derives the unfiltered collection directly and scans it in chunks when a filter is active.
| Feature | Runtime Rule |
|---|---|
| Exact id search | updateExactSearch() detects pal_... or numeric input and
sets state.exactSearchIndex. |
| Method filter | keepFrom() keeps chunk palettes whose method matches before the other
filters run. |
| Unfiltered window | materialise(first, last) derives only the rows in view, so row i is
palette i. |
| Random sort | Shuffle sets the sort to random; like every non-original sort it orders a bounded scan
from scanTo(SORT_SCAN). |
| Local search | HEX, method text and palette id terms filter each scanned chunk unless an exact id was found. |
| Local filters | Hue, chroma and lightness filters run in localFilterOnly() over
each scanned chunk of 1,500 palettes. |
| Local sort | Sorts the scanned matches by lightness, chroma, hue or random order. |
Search is debounced at 90 ms. Filter and sort changes call applyFilters(), which resets the scan and calls
renderPage().
10. Rendering and interaction model
+paletteCardInner()builds grid cards with swatches, palette id, method badge, Inspect, Copy and Save controls.- Clicking a swatch copies that swatch HEX.
- Clicking Copy copies all five palette HEX values.
- Clicking Save toggles local saved state and workspace mirroring.
- Clicking the card body or Inspect calls
openInspect(palette). - Keyboard Enter or Space on a focused card opens Inspect.
- Pressing / focuses search unless an input or textarea is already active.
selectTab() toggles tab ARIA state and lazy-renders panels. Export and Saved panel
output is refreshed on each open because those views depend on current selection and local saved
ids.
11. Panel responsibilities
+| Panel | Function |
|---|---|
Inspect |
Renders palette strip, summary metrics, pair contrast list, per-color RGB, Lab, OKLCH and WCAG contrast plus selected-palette export actions. |
Harmony |
Summarizes the sampled palettes by method, hue bucket, harmony classification and chroma/lightness profile. |
Accessibility |
Computes any-AA palettes, any-AAA palettes, pair-level AA/AAA counts, mutually legible set sizes and the most usable palettes. |
Stats |
Builds histograms for average lightness, average chroma, hue spread and best pair contrast. |
Export |
Shows selected-palette copy/download buttons and bulk export buttons for the analysis sample. |
Saved |
Reads local saved ids, materializes those palettes and renders palette cards with a workspace link. |
12. Export system
+
exportPalette() handles selected-palette exports. exportBulk() handles
state.visiblePalettes, the analysis sample. Clipboard writes use navigator.clipboard with a textarea
fallback.
stripPalette()returnspalette_id, colors and metadata.buildAse()creates an Adobe Swatch Exchange binary using RGB records.buildSvg()creates a 600 x 220 SVG palette strip with HEX labels.buildPng()creates an 800 x 320 canvas palette strip and downloads a PNG.- Selected CSS export writes a
:rootblock with--{palette_id}-{n}variables. - Selected Tailwind export writes a JSON object keyed by palette id.
- Bulk Tailwind export writes a
module.exportsconfig fragment.
{
"palette_id": "pal_abc",
"colors": [
{
"hex": "#aabbcc",
"rgb": [170, 187, 204],
"oklch": [0.78, 0.04, 248.2],
"lab": [75.1, -2.4, -11.3]
}
],
"metadata": {
"method": "triadic",
"color_count": 5,
"deltaE_avg": 42.5,
"entropy": 0.6,
"contrast_matrix": [[1, 2.4]]
}
}
Bulk CSV columns are palette_id, method, c1,
c2, c3, c4 and c5.
14. Accessibility and UX rules
+- The app container uses
role="application"and the tab bar is a nav labelledaria-label="Palette sections". - Tabs use
role="tablist",role="tab",aria-selectedandaria-controls. - Panels use
role="tabpanel"with matching labels. - The grid uses
aria-live="polite"so result changes can be announced. - The toast uses
role="status"andaria-live="polite". - Cards support keyboard activation with Enter and Space.
- All seven tabs are always available; there is no Simple or Advanced mode to hide them.
- The result counter
plib-page-infousesrole="status"andaria-live="polite".
Preserve visible text labels for important actions. Tooltips help expert users, but buttons should still make sense without hover.
15. Performance, validation and maintenance
+The virtual manifest keeps the page practical. Avoid changing it into an expanded JSON browser unless the UX and delivery architecture are redesigned.
- Keep manifest count, hero count, page metadata and docs aligned.
- Do not change
seed,batch_sizeorbatch_seed_stridewithout treating palette ids as migrated data. - Keep
methodForIndex()andkeepFrom()synchronized with manifest method rules. - Update docs when hue buckets, chroma thresholds, lightness thresholds or sort modes change.
- Validate clipboard, ASE, SVG, PNG and URL object cleanup when changing exports.
- Check localStorage migration before changing
SAVED_KEYor saved id format. - After documentation changes, regenerate documentation discovery, feeds, sitemaps, PWA cache and search index.
node scripts/generate-discovery.mjs
node scripts/generate-pwa-cache-manifest.mjs
node search/client/build-index.js
For user-facing workflow details, see the Palette Library User Guide. For generator internals, see the Palette Gen Developer Reference.