Quick Start
This guide shows how to create and validate your first PaletteJSON file.
Minimal file
A minimal valid file contains at least one palette, with a name, slug, type, and two or more colors.
- Bare Minimum
{
"palettes": [
{
"name": "Example",
"slug": "example",
"type": "categorical",
"colors": [{ "hex": "#FFFFFF" }, { "hex": "#000000" }]
}
]
}
- name — human-readable label for the palette.
- slug — URL-safe identifier (lowercase letters, numbers, hyphens).
- type — one of
categorical,sequential,diverging. - colors — array with at least two colors.
color values
Each color can be defined with hex (#RRGGBB or #RRGGBBAA) or components (numeric array interpreted by a palette-level colorRepresentation).
If both are present, consumers should treat components as authoritative and use hex for preview/interoperability.
File identification
To make your file portable:
- Extension:
.palette.json - Encoding: UTF-8
- Media type:
application/prs.palettejson+json(fall back toapplication/jsonif needed) - Apple UTI (optional):
org.palettejson.json.
note
These identifiers are recommendations for tooling and do not affect schema validity.
Validating a file
You can validate PaletteJSON against the official schema (palettejson.schema.json), which targets JSON Schema draft 2020-12.
- Node.js (AJV v8)
- Python (jsonschema)
// Install: npm i ajv
import Ajv from "ajv";
import addFormats from "ajv-formats";
import schema from "./palettejson.schema.json" assert { type: "json" };
// Example data
const data = {
palettes: [
{
name: "Example",
slug: "example",
type: "categorical",
colors: [{ hex: "#FFFFFF" }, { hex: "#000000" }],
},
],
};
const ajv = new Ajv({ strict: false }); // strict off if you prefer fewer warnings
addFormats(ajv);
const validate = ajv.compile(schema);
const valid = validate(data);
if (valid) {
console.log("Valid!");
} else {
console.error("Validation errors:", validate.errors);
}
# Install: pip install jsonschema
import json
from jsonschema import validate, Draft202012Validator
# Load the schema file (placed next to this script)
with open("palettejson.schema.json", "r", encoding="utf-8") as f:
schema = json.load(f)
# Example data
data = {
"palettes": [
{
"name": "Example",
"slug": "example",
"type": "categorical",
"colors": [{"hex": "#FFFFFF"}, {"hex": "#000000"}]
}
]
}
# Optional: sanity-check the schema itself
Draft202012Validator.check_schema(schema)
# Validate
validate(instance=data, schema=schema)
print("Valid!")
Validation rules
- If any color in a palette uses
components, the palette must declarecolorRepresentation. - If any color has a
position, all colors in that palette must have aposition(1-based). - Grouping constraint: At most one color per
groupIdmay havereferenceInGroup: true(requires external validation). hexis always interpreted as display sRGB; alpha (if present) is the last pair:#RRGGBBAA.- Component ranges depend on
colorRepresentation:sRGB/DisplayP3: 3–4 numbers, each in [0, 1]sRGB-linear-extended: either 3 numbers (unbounded) or 4 with alpha in [0, 1]Lab: 3–4 numbers; L in [0, 100], a/b unbounded, optional alpha in [0, 1]OKLCH: 3–4 numbers; L in [0, 1], C ≥ 0, h ∈ [0, 360), optional alpha in [0, 1]HSL: 3–4 numbers; H in [0, 360), S/L in [0, 1], optional alpha in [0, 1]
- Contrast ratios in
legibilitymust be between 1 and 21 (WCAG 2.x maximum).
Next steps
- Read the Root object and Palette specs for required/optional fields.
- See the Color page for
hexvscomponents,references,position, and legibility metadata. - Learn about choosing color spaces, precision requirements, and gamut mapping.
- Explore Examples for richer use cases.