{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://beyond-kle.org/schemas/phy-layer.json", "title": "PHY Layer - Physical Key Layout", "description": "Physical positioning and sizing of keys", "type": "object", "required": ["version", "metadata", "profiles", "root"], "properties": { "version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$", "description": "Schema version (semver)" }, "metadata": { "type": "object", "properties": { "name": { "type": "string" }, "author": { "type": "string" }, "description": { "type": "string" }, "created": { "type": "string", "format": "date-time" }, "modified": { "type": "string", "format": "date-time" } } }, "kleCompatibility": { "type": "object", "description": "File-level opaque KLE fields kept for round-trip output (switchMount, switchBrand, switchType, backcolor, radii, background, css). Kept here for now; the eventual owning layer is deferred in backlog/README.md, PHY-P-6", "additionalProperties": true }, "profiles": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/profile" } }, "root": { "type": "array", "items": { "oneOf": [ { "$ref": "#/$defs/key" }, { "$ref": "#/$defs/cluster" }, { "$ref": "#/$defs/component" }, { "$ref": "#/$defs/variantGroup" } ] } } }, "$defs": { "transform": { "type": "object", "description": "Placement relative to the parent: rotate by rotation around the local origin, then translate by (x, y)", "required": ["x", "y", "rotation"], "properties": { "x": { "type": "number" }, "y": { "type": "number" }, "rotation": { "type": "number", "description": "Degrees" } } }, "profile": { "type": "object", "required": ["id", "name", "unitSize"], "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "unitSize": { "type": "object", "description": "Millimeters per 1U", "required": ["x", "y"], "properties": { "x": { "type": "number", "minimum": 0 }, "y": { "type": "number", "minimum": 0 } } }, "visualOffset": { "type": "object", "description": "Key top rectangle, in millimeters: inward distance from each edge of the outline, plus corner radius", "required": ["top", "right", "bottom", "left", "radius"], "properties": { "top": { "type": "number" }, "right": { "type": "number" }, "bottom": { "type": "number" }, "left": { "type": "number" }, "radius": { "type": "number", "minimum": 0 } } } } }, "key": { "type": "object", "required": ["type", "id", "profile", "transform", "size"], "properties": { "type": { "type": "string", "const": "key" }, "id": { "type": "string", "description": "Unique key identifier" }, "profile": { "type": "string", "description": "Reference to profile ID" }, "transform": { "$ref": "#/$defs/transform" }, "size": { "type": "object", "description": "Local size. Not affected by the parent transform", "required": ["w", "h"], "properties": { "w": { "type": "number", "minimum": 0 }, "h": { "type": "number", "minimum": 0 }, "x2": { "type": "number", "description": "Second rectangle for non-rectangular keys, relative to the local origin" }, "y2": { "type": "number" }, "w2": { "type": "number", "minimum": 0 }, "h2": { "type": "number", "minimum": 0 } } }, "switchOffset": { "type": "object", "description": "Switch position, offset from the center of the (w, h) rectangle. Key local coordinates, unit U. Defaults to 0", "required": ["x", "y"], "properties": { "x": { "type": "number" }, "y": { "type": "number" } } }, "partGroup": { "type": "string", "description": "Label grouping keys that use the same part. Not interpreted by Beyond KLE" }, "orientation": { "type": "integer", "enum": [0, 90, 180, 270], "default": 0, "description": "Switch orientation in the key local coordinates" }, "perKeyLED": { "type": "boolean", "default": false, "description": "Whether a per-key LED is mounted" }, "decal": { "type": "boolean", "default": false }, "ghost": { "type": "boolean", "default": false }, "labels": { "type": "array", "items": { "type": "string" }, "description": "Reference information. Used for matching on KLE JSON import" }, "kleCompatibility": { "type": "object", "description": "Opaque KLE fields kept for round-trip output (c, t, p, a, f, f2, fa, l, n, sm, sb, st). Kept here for now; the eventual owning layer is deferred in backlog/README.md, PHY-P-6", "additionalProperties": true } } }, "component": { "type": "object", "description": "Non-key part placed by the designer (LED, OLED, encoder, screw hole, ...)", "required": ["type", "id", "transform"], "properties": { "type": { "type": "string", "const": "component" }, "id": { "type": "string" }, "transform": { "$ref": "#/$defs/transform" }, "partGroup": { "type": "string", "description": "Names starting with @ are reserved for editor rendering" } } }, "variantGroup": { "type": "object", "description": "Mutually exclusive layout alternatives. Children are variants only", "required": ["type", "id", "name", "transform", "default", "children"], "properties": { "type": { "type": "string", "const": "variantGroup" }, "id": { "type": "string" }, "name": { "type": "string", "description": "Heading shown for the choice in the editor" }, "transform": { "$ref": "#/$defs/transform" }, "default": { "type": "string", "description": "id of the variant used when a single layout must be chosen" }, "children": { "type": "array", "minItems": 2, "description": "Display order", "items": { "$ref": "#/$defs/variant" } } } }, "variant": { "type": "object", "description": "One alternative. Appears only directly under a variantGroup. Carries no transform", "required": ["type", "id", "name", "children"], "properties": { "type": { "type": "string", "const": "variant" }, "id": { "type": "string" }, "name": { "type": "string" }, "children": { "type": "array", "description": "May be empty", "items": { "oneOf": [ { "$ref": "#/$defs/key" }, { "$ref": "#/$defs/cluster" }, { "$ref": "#/$defs/component" }, { "$ref": "#/$defs/variantGroup" } ] } } } }, "cluster": { "type": "object", "required": ["type", "id", "transform", "children"], "properties": { "type": { "type": "string", "const": "cluster" }, "id": { "type": "string" }, "name": { "type": "string" }, "transform": { "$ref": "#/$defs/transform" }, "children": { "type": "array", "items": { "oneOf": [ { "$ref": "#/$defs/key" }, { "$ref": "#/$defs/cluster" }, { "$ref": "#/$defs/component" }, { "$ref": "#/$defs/variantGroup" } ] } } } } } }