Home
void ANT

The LayerZip Specification

LayerZip is a program independent way to store 2d image layers using zip deflate, png, and a json file. it intentionally avoids any proprietary features that only 1 or a few programs support for maximum interoperability.

Table Of Contents

Table Of Contents
  1. The LayerZip Specification
    1. Table Of Contents
    2. Status of this document
    3. This Specification uses external references
    4. Examples of LayerZip in use
    5. The Zip Structure
      1. The Configuration JSON
        1. Root Level Object
        2. Layer Object
        3. PathSanitization
      2. Folder Structure
      3. File Settings
    6. Application Behavior
      1. Error Handling
    7. Future Goals
    8. Author's Notes

Status of this document

this document written on Sun Mar 01 2026 is the latest LayerZip Specification Semantic version 0.0.1. this is self-published independently.

This Specification uses external references

  • The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
  • PNG (Wikipedia)
  • ZIP (Wikipedia)
  • DEFLATE (Wikipedia)
  • JSON (Wikipedia)

Examples of LayerZip in use

link to examples, for now, there are none that fully implement this specification. should be an <ul> of links.
  • DNSCond/multiexport-krita-plugi; Reference Implementation. note that if it is wrong then check the spec and if they contradict the Reference Implementation is at fault. can only export for now.

The Zip Structure

  • at the top level, the all LayerZip files MUST have a directory. this is called the root directory
  • inside that directory there MUST be a file called layerzip.json with content described in The Configuration JSON.
  • There MUST be exactly 1 layerzip.json file and it must be in the root directory

The Configuration JSON

Formal JSON Schema
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "LayerZip Configuration",
  "type": "object",
  "required": [
    "specVersion",
    "width",
    "height",
    "layers"
  ],
  "properties": {
    "specVersion": {
      "type": "string",
      "pattern": "^0\\.0\\.1$",
      "description": "the specification version. MUST be matched against the specification for disambiguation. in this schema it MUST be {\"0.0.1\"}. SHOULD be matched to disambiguate specifics of a LayerZip spec",
      "$comment": "in terms of regex it must be {\"^\\d+\\.\\d+\\.\\d+$\"}"
    },
    "width": {
      "type": "integer",
      "minimum": 1,
      "description": "MUST be the Width of the canvas, in pixels."
    },
    "height": {
      "type": "integer",
      "minimum": 1,
      "description": "MUST be the Height of the canvas, in pixels."
    },
    "layers": {
      "type": "array",
      "description": "MUST be an array of layers",
      "items": {
        "$ref": "#/definitions/layer"
      }
    }
  },
  "definitions": {
    "layer": {
      "type": "object",
      "description": "a layer",
      "required": [
        "type",
        "name",
        "path"
      ],
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "rasterlayer",
            "vectorlayer",
            "grouplayer"
          ],
          "description": "MUST be one of {\"rasterlayer\"} if a png is associated, {\"vectorlayer\"} if a svg is associated, {\"grouplayer\"} if a directory is associated."
        },
        "name": {
          "type": "string",
          "description": "the layer's name as seen in the editor. SHOULD be matched exactly."
        },
        "path": {
          "type": "string",
          "description": "the layer's path. MUST be Normalized. the path MUST start from the {\"layerzip.json\"}."
        },
        "visible": {
          "type": "boolean",
          "description": "if omitted MUST default to {{true}}. if present MUST be a json boolean representing if its visible in the editor. must be the actual layer content even if the layer is set to be visible false.",
          "default": true
        },
        "locked": {
          "type": "boolean",
          "description": "if omitted MUST default to {{false}}. if present MUST be a json boolean representing if its locked in the editor. if the editor doesnt support layer locking then put false.",
          "default": false
        },
        "opacity": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "if omitted MUST default to {{1}}. if present MUST be a json number representing its opacity.",
          "default": 1
        },
        "layers": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/layer"
          },
          "description": "if omitted MUST default to an empty array. MUST only exist if the type is {\"grouplayer\"}."
        },
        "blendMode": {
          "type": "string",
          "enum": [
            "normal",
            "multiply",
            "screen",
            "overlay",
            "color-dodge",
            "color-burn",
            "hard-light",
            "soft-light",
            "difference"
          ],
          "default": "normal",
          "description": "Blend mode following CSS / Porter-Duff naming conventions. If omitted or unknown, MUST fallback to 'normal'. Editors SHOULD support at least the first four values."
        }
      }
    }
  }
}

Root Level Object

Field NameTypeField RequirementsRequiredField Description
specVersionstringstring MUST match /^0\.0\.1$/ json regxepTruethe specification version. MUST be matched against the specification for disambiguation. in this schema it MUST be 0.0.1. SHOULD be matched to disambiguate specifics of a LayerZip spec
widthinteger1 <= NTrueMUST be the Width of the canvas, in pixels.
heightinteger1 <= NTrueMUST be the Height of the canvas, in pixels.
layersarrayNoneTrueMUST be an array of layers

Layer Object

Field NameTypeField RequirementsRequiredField Description
typestringone of
  • rasterlayer
  • vectorlayer
  • grouplayer
TrueMUST be one of rasterlayer if a png is associated, vectorlayer if a svg is associated, grouplayer if a directory is associated.
namestringNoneTruethe layer's name as seen in the editor. SHOULD be matched exactly.
pathstringNoneTruethe layer's path. MUST be Normalized. the path MUST start from the layerzip.json.
visiblebooleanNoneFalseif omitted MUST default to true. if present MUST be a json boolean representing if its visible in the editor. must be the actual layer content even if the layer is set to be visible false.
lockedbooleanNoneFalseif omitted MUST default to false. if present MUST be a json boolean representing if its locked in the editor. if the editor doesnt support layer locking then put false.
opacitynumber0 <= N <= 1Falseif omitted MUST default to 1. if present MUST be a json number representing its opacity.
layersarrayNoneFalseif omitted MUST default to an empty array. MUST only exist if the type is grouplayer.
blendModestringone of
  • normal
  • multiply
  • screen
  • overlay
  • color-dodge
  • color-burn
  • hard-light
  • soft-light
  • difference
FalseBlend mode following CSS / Porter-Duff naming conventions. If omitted or unknown, MUST fallback to 'normal'. Editors SHOULD support at least the first four values.

PathSanitization

While the Full Path Sanitization is implementation-defined, implementations MUST make sure the path follows these rules.

  • File names and directory names MUST NOT contain any of the following characters:
    • \
    • /
    • :
    • *
    • ?
    • "
    • <
    • >
    • |
    These characters are forbidden on Windows; restricting them ensures maximum cross-platform interoperability.
  • Paths MUST use / as the path separator.
  • Paths MUST NOT contain upward directory indicators (..) or current directory indicators (.).
  • Paths MUST NOT reference any files located outside the ZIP root directory.

Folder Structure

The LayerZip file requires a specific folder structure. At the root level, all layers that are not in groups MUST be placed directly in the root directory. Layers that belong to a group MUST be placed in a subdirectory named for that group. Layer paths in layerzip.json MUST exactly match their relative paths from the layerzip.json file, using / as the path separator. Implementations SHOULD normalize paths (e.g., remove redundant ./ or ../ segments), but the exact normalization method is implementation-defined. Nested groups are allowed. If a group is referenced in layerzip.json, its directory MUST exist in the archive. The directory MAY be empty if no layers are currently assigned to that group, and tools SHOULD preserve empty directories to maintain group hierarchy.

Example folder structure:

/layerzip.json
/background.png
/foreground.png
/characters/hero.png
/characters/enemies/villain.png
/props/           (empty group directory allowed)

Layers MUST be ordered by array index; layers with a higher index MUST be displayed in front of layers with lower indices.

File Settings

  • All PNG files used within a LayerZip archive MUST be 8-bit or 16-bit per channel RGBA and MUST have the sRGB color profile embedded, or be implicitly treated as sRGB.
  • The LayerZip archive MUST use the ZIP file format. Compressed files within the archive MUST be compressed using the DEFLATE algorithm (as defined in RFC 1951).

Application Behavior

Compliant software implementations MUST follow these rules when handling a LayerZip file:

  • Loading: Software MUST unzip the archive and parse the layerzip.json file to determine project structure.
  • Canvas Setup: The project canvas MUST be initialized to the width and height specified in the JSON.
  • Layer Assembly: Images MUST be loaded into layers corresponding to their paths in the JSON. Layers MUST be stacked in the order defined by the array index (higher index = higher z-order). If an image file referenced in the JSON is missing from the ZIP, the software MUST treat that layer as empty (fully transparent) and NOT abort the loading process.
  • Attributes: The software MUST respect the visible, locked, and opacity values for each layer. If a layer is set to visible: false, the software MUST still load the image data to ensure it is immediately available if toggled on by the user.

Error Handling

Implementations MUST handle errors gracefully to maintain user data integrity. If a required file is missing, the application SHOULD NOT crash, but rather render the layer as empty and notify the user. If the layerzip.json file is invalid or corrupted, the application MUST alert the user and refuse to load the project. Sanitization of file paths is REQUIRED to prevent path traversal vulnerabilities.

other than that programs SHOULD attempt to do the following when a spec Violation Occurs:

A Path references a file outside the root directory.
A Path references a no file nor directory.
Insert a transparent layer in its place and alert the user.
A Path contains an upward directory indicators (..) or current directory indicators (.).
Traverse the path. if it is within the root directory the implementation MAY load that image as path. if the implementation does not want to do that or the path references a file outside the root directory they MAY Insert A transparent layer in its place and alert the user, as the upward directory indicators (..) and current directory indicators (.) are technically spec violations.

Future Goals

  • feature complete DNSCond/multiexport-krita-plugi; Reference Implementation to this full specification
  • clarify and copywrite this document.
  • fill out gaps.
  • add more examples.

Author's Notes

please tell me how i did. it was my first time writing something like this. this is self-published independently.