PaletteJSON Specification

website·Indexed 29 days ago

https://palettejson.org

An open JSON schema for defining color palettes in a structured, machine-readable way. The documentation covers the schema specification for root objects, palettes, colors, and accessibility, as well as guides on color space selection, gamut mapping, and precision.

Tokens
10.3K
Snippets
42
Records
73
Agent score
49%

What's inside PaletteJSON

  1. Overview of the PaletteJSON schema

    PaletteJSON is an open, machine-readable JSON schema used to define color palettes. It serves as an interoperable "hub" format (lingua franca) to allow color palettes to be easily stored, exchanged, and extended across various tools and workflows. Its design focuses on clarity (using standard JSON), extensibility (supporting metadata and multiple color spaces), and interoperability.
  2. Overview of PaletteJSON schema

    PaletteJSON is a JSON schema used to describe color palettes in a portable, machine-readable format. It is designed for developers, designers, and tool authors to consistently load, export, and share color systems, including associated metadata and accessibility information. The current stable version documented is v0.1, though the project is considered experimental and subject to future changes in features or validation rules.
  3. Parse and validate PaletteJSON files

    Use a JSON schema validator (like Ajv) to ensure PaletteJSON files are compliant. When extracting colors, prefer the components array over the hex string for higher precision, using the colorRepresentation field to determine the color space.
    import Ajv from "ajv";
    import addFormats from "ajv-formats";
    import schema from "./palettejson.schema.json" assert { type: "json" };
    import Color from "colorjs.io";
    
    const ajv = new Ajv({ strict: false });
    addFormats(ajv);
    const validate = ajv.compile(schema);
    
    const data = JSON.parse(fileContents);
    if (validate(data)) {
      const { colorRepresentation, colors } = data;
      const extracted = colors.map((color) => {
        if (color.components) {
          return new Color(colorRepresentation.toLowerCase(), color.components);
        } else if (color.hex) {
          return new Color(color.hex);
        }
      });
    }
  4. Test color round-trip accuracy using colorjs.io

    Verify if your decimal precision is sufficient by performing a round-trip conversion and calculating the perceptual difference (ΔE 2000). If the ΔE 2000 exceeds 1.0, increase the decimal precision by one place and test again.

    Interpreting ΔE 2000 values:

    • < 1.0: Imperceptible difference (Excellent).
    • 1.0 - 2.0: Perceptible only under close comparison (Acceptable).
    • 2.0 - 3.0: Noticeable difference (Marginally acceptable).
    • > 3.0: Clearly visible difference (Insufficient precision).
    import Color from "colorjs.io";
    
    // Original sRGB color
    const original = new Color("srgb", [0.9608, 0.8784, 0.8627]);
    
    // Convert to Lab and back to sRGB
    const lab = original.to("lab");
    const roundTrip = lab.to("srgb");
    
    // Calculate perceptual difference
    const deltaE = original.deltaE(roundTrip, "2000");
    console.log(`ΔE 2000: ${deltaE.toFixed(4)}`);
  5. Implement legibility guidance for UI consumers

    When consuming PaletteJSON legibility data:

    1. Use preferredText as a high-level recommendation for direct UI application.
    2. Treat luminance and contrast ratios as numeric hints, as different consumers may calculate them differently.
    3. If the legibility object or its properties are absent, the consumer should calculate or infer the legibility values as needed.
  6. Maintain precision and test round-trip accuracy

    Color conversions accumulate errors. To prevent perceptual drift, maintain 4-5 decimal places for Lab and OKLCH values. Verify critical brand colors by performing a 'round-trip' conversion (e.g., sRGB → Lab → sRGB) and ensuring the Delta E ($ΔE$) 2000 difference is less than 1.0.
    import Color from "colorjs.io";
    
    function testRoundTrip(hexColor) {
      const original = new Color(hexColor);
    
      // Test via Lab
      const viaLab = original.to("lab").to("srgb");
      const labDelta = original.deltaE(viaLab, "2000");
    
      // Test via OKLCH
      const viaOKLCH = original.to("oklch").to("srgb");
      const oklchDelta = original.deltaE(viaOKLCH, "2000");
    
      return { labDelta, oklchDelta }; // Both should be < 1.0
    }
    
    testRoundTrip("#f5e0dc");
  7. Recommended libraries for color conversion and validation

    Use established libraries for color manipulation and schema validation to ensure precision and compliance.
    # Color Conversion
    npm install colorjs.io  # JavaScript
    pip install coloraide  # Python
    
    # Validation
    npm install ajv ajv-formats  # Node.js
    pip install jsonschema      # Python
  8. Best practices for using PaletteJSON color references

    When mapping PaletteJSON colors to external systems, follow these guidelines:

    1. Only provide references when you have an authoritative mapping.
    2. Use only one reference per system to maintain clarity.
    3. Use the note property to document any uncertainties or special cases regarding the mapping.
  9. Perform color conversions using recommended libraries

    Avoid implementing color space mathematics from scratch due to complexity and error risk. Use established libraries to handle gamma correction and edge cases.

    Recommended Libraries:

    • JavaScript: colorjs.io, Culori
    • Python: coloraide, color-science
    • Rust: palette
    • Swift: SwiftColor
    // ✅ CORRECT: Use a library like colorjs.io
    import Color from "colorjs.io";
    const hsl = new Color("srgb", [r, g, b]).to("hsl");
  10. Validate a PaletteJSON file using Node.js and AJV

    PaletteJSON files can be validated against the official palettejson.schema.json using JSON Schema draft 2020-12. In Node.js, this is typically done using the ajv and ajv-formats libraries.
    // Install: npm i ajv ajv-formats
    import Ajv from "ajv";
    import addFormats from "ajv-formats";
    import schema from "./palettejson.schema.json" assert { type: "json" };
    
    const data = {
      palettes: [
        {
          name: "Example",
          slug: "example",
          type: "categorical",
          colors: [{ hex: "#FFFFFF" }, { hex: "#000000" }],
        },
      ],
    };
    
    const ajv = new Ajv({ strict: false });
    addFormats(ajv);
    
    const validate = ajv.compile(schema);
    const valid = validate(data);
    
    if (valid) {
      console.log("Valid!");
    } else {
      console.error("Validation errors:", validate.errors);
    }
  11. Manage HDR and Wide-Gamut workflows in PaletteJSON

    PaletteJSON has specific constraints for high-dynamic-range and wide-gamut data:

    • HDR (Rec. 2020, Dolby Vision): Use sRGB-linear-extended with unbounded RGB values. Store HDR metadata externally as PaletteJSON does not natively support it.
    • ACES AP1: Not natively supported; store in altRepresentations.
    • ICC Profiles: PaletteJSON does not embed ICC profiles. Store profile metadata in the notes field or reference external .icc files via the palette slug or id.
  12. Choose a PaletteJSON color representation

    PaletteJSON supports six color representations optimized for different workflows. Use the following decision logic to select the appropriate one:

    1. Need wide-gamut colors beyond sRGB?
      • Yes: Use DisplayP3 (modern displays) or sRGB-linear-extended (HDR workflows).
      • No: Proceed to step 2.
    2. Need perceptually uniform color manipulation?
      • Yes: Use OKLCH (modern) or Lab (industry standard).
      • No: Proceed to step 3.
    3. Need intuitive hue-based controls for designers?
      • Yes: Use HSL or OKLCH.
      • No: Use sRGB (maximum compatibility).