Skip to main content
Auric Artisan · Documentation

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.

Updated: May 26, 2026 Route: /library/palette/ Runtime: palette-library.js Author: Chirag Bansal
Back to Documentation Auric Artisan Home

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.

Table of contents

  1. 1. Runtime overview
  2. 2. File and dependency map
  3. 3. Page shell, SEO and UI Chrome
  4. 4. DOM contract
  5. 5. Manifest contract
  6. 6. Virtual Palette Generation
  7. 7. State and load sequence
  8. 8. Color science helpers
  9. 9. Filtering, sorting and scrolling
  10. 10. Rendering and interaction model
  11. 11. Panel responsibilities
  12. 12. Export system
  13. 13. Save, share and token dialog
  14. 14. Accessibility and UX rules
  15. 15. Performance, validation and maintenance

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) computes seed + batch * batch_seed_stride.
  • paletteId(index) returns pal_ plus the base-36 index.
  • indexFromPaletteId(id) accepts pal_... 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
  }
}
  1. Resolve DOM ids into els.
  2. Attach event listeners for search, filters, cards, exports, tabs and the back-to-top button.
  3. Call loadData().
  4. Fetch and normalize the deterministic manifest.
  5. Populate method filter options.
  6. Build the analysis sample and give the virtual grid its source.
  7. Render saved panel state and register the palette share handler.

8. Color science helpers

+
  • rgbToHex() serializes generated RGB triples.
  • rgbToLab() computes CIE Lab values for inspection and Delta E average.
  • rgbToOklab() and rgbToOklch() 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() and maxPairContrast() 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() returns palette_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 :root block with --{palette_id}-{n} variables.
  • Selected Tailwind export writes a JSON object keyed by palette id.
  • Bulk Tailwind export writes a module.exports config 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.

13. Save, share and token dialog

+
  • getSaved() reads aa.palette.saved.
  • setSaved() stores up to 500 palette ids.
  • toggleSaved(id) updates local saved state, mirrors adds with mirrorSave() and removes with mirrorRemove().
  • mirrorSave() stores domain palette, asset type palette, tool id library-palette, description, colors and payload.
  • sharePaletteLink() calls shareViaDialog() with type palette.
  • registerShareHandler("palette", hydrateFromSharedPalette) opens a matching deterministic palette from a shared id.
  • openTokensDialog() uses default prefix brand and tokensFromSwatchList().

Shared payloads include id, uppercase colors and method. Hydration currently resolves by id; it does not create synthetic palettes from inline colors when the id is absent or invalid.

14. Accessibility and UX rules

+
  • The app container uses role="application" and the tab bar is a nav labelled aria-label="Palette sections".
  • Tabs use role="tablist", role="tab", aria-selected and aria-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" and aria-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-info uses role="status" and aria-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_size or batch_seed_stride without treating palette ids as migrated data.
  • Keep methodForIndex() and keepFrom() 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_KEY or 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.