Penpot File Format (.penpot) #

The .penpot file format is Penpot's native export format for design files. It's a ZIP archive containing JSON metadata and binary assets, designed to be open, inspectable, and efficient.

Overview #

The .penpot format (version 3) uses a ZIP container with JSON files for metadata and binary files for media assets. This approach provides several advantages:

  • Open and inspectable: All metadata is human-readable JSON
  • Efficient: ZIP compression reduces file size
  • Interoperable: Standard formats enable third-party tooling
  • Versioned: Clear versioning system for format and data evolution

Version History #

Version Description Status
v1 Custom binary format Deprecated
v2 SQLite-based format Never released (internal only)
v3 ZIP + JSON format Current

File Structure #

A .penpot file contains the following structure:

pencil.penpot (ZIP archive)
├── manifest.json                          # Root metadata
├── files/
│   ├── {file-id}.json                     # File metadata
│   └── {file-id}/
│       ├── pages/
│       │   ├── {page-id}.json             # Page metadata
│       │   └── {page-id}/
│       │       └── {shape-id}.json        # Individual shapes
│       ├── media/
│       │   └── {media-id}.json            # Media references
│       ├── colors/
│       │   └── {color-id}.json            # Library colors
│       ├── components/
│       │   └── {component-id}.json        # Library components
│       ├── typographies/
│       │   └── {typography-id}.json       # Library typographies
│       ├── tokens.json                    # Design tokens library
│       └── thumbnails/
│           └── {tag}/{page-id}/{frame-id}.json  # Thumbnail metadata
└── objects/
    ├── {uuid}.json                        # Storage object metadata
    └── {uuid}.{ext}                       # Binary media files (png, jpg, etc.)

Manifest Specification #

The manifest.json file is the root of the archive and contains metadata about the export.

Schema #

{
  "version": 1,
  "type": "penpot/export-files",
  "generatedBy": "penpot/2.12.0",
  "refer": "penpot",
  "files": [
    {
      "id": "uuid",
      "name": "File Name",
      "features": ["feature1", "feature2"]
    }
  ],
  "relations": []
}

Fields #

Field Type Required Description
version integer Yes Format version (currently 1)
type string Yes Must be "penpot/export-files"
generatedBy string No Penpot version that created the file
refer string No Source system (typically "penpot")
files array Yes List of files in the archive
files[].id UUID Yes File identifier
files[].name string Yes File name
files[].features array Yes Set of feature flags
relations array No Library relationships [file-id, library-id]

Example #

{
  "type": "penpot/export-files",
  "version": 1,
  "generatedBy": "penpot/2.12.0-RC1-99-g40c27591f",
  "refer": "penpot",
  "files": [
    {
      "id": "73b59a94-3ea3-8189-8007-3d36adc8c3e3",
      "name": "Pencil | Penpot Design System",
      "features": [
        "fdata/path-data",
        "design-tokens/v1",
        "variants/v1",
        "layout/grid",
        "components/v2",
        "fdata/shape-data-type"
      ]
    }
  ],
  "relations": []
}

File Metadata #

Each file has a JSON file at files/{file-id}.json containing the file's metadata.

Schema #

Field Type Required Description
id UUID Yes File identifier
name string Yes File name
revn integer Yes Revision number
vern integer No Version number
createdAt timestamp Yes Creation timestamp
modifiedAt timestamp Yes Last modification timestamp
deletedAt timestamp No Deletion timestamp (if soft-deleted)
projectId UUID No Project identifier
teamId UUID No Team identifier
isShared boolean No Whether file is a shared library
hasMediaTrimmed boolean No Whether media has been trimmed
features array Yes Set of enabled feature flags
migrations array No List of applied data migrations
options object No File-level options

Features #

The features field is a set of strings indicating which features are enabled in the file. Common features include:

Feature Description
fdata/path-data Path data format
fdata/shape-data-type Shape data type system
design-tokens/v1 Design tokens support
variants/v1 Component variants
layout/grid Grid layout system
components/v2 Component system v2
plugins/runtime Plugin runtime support

Migrations #

The migrations field lists all data migrations applied to the file. This ensures backward compatibility when the data model evolves.

Example #

{
  "id": "73b59a94-3ea3-8189-8007-3d36adc8c3e3",
  "name": "Pencil | Penpot Design System",
  "revn": 28425,
  "vern": 0,
  "createdAt": "2025-12-10T10:24:18.686066Z",
  "modifiedAt": "2025-12-10T12:13:49.799076Z",
  "teamId": "b62e1aa4-d9a7-8147-8005-2813bed4056e",
  "projectId": "f23add0e-6b77-8069-8005-41b48b93a5da",
  "isShared": true,
  "features": [
    "fdata/path-data",
    "design-tokens/v1",
    "variants/v1",
    "layout/grid",
    "components/v2",
    "fdata/shape-data-type"
  ],
  "migrations": [
    "legacy-2",
    "legacy-3",
    "0001-remove-tokens-from-groups",
    "0002-normalize-bool-content-v2"
  ],
  "options": {
    "componentsV2": true
  }
}

Pages and Shapes #

Page Structure #

Each page is stored at files/{file-id}/pages/{page-id}.json.

Field Type Required Description
id UUID Yes Page identifier
name string Yes Page name
index integer No Page order in the file
options object No Page options (guides, etc.)
background string No Background color (hex)
flows object No Prototype flows
guides object No Ruler guides

Shapes #

Individual shapes are stored at files/{file-id}/pages/{page-id}/{shape-id}.json.

Shape Types #

Penpot supports 9 shape types:

Type Description
frame Container frame (artboard)
group Group of shapes
rect Rectangle
circle Circle/Ellipse
path Vector path
text Text shape
image Image
bool Boolean operation
svg-raw Raw SVG element

Base Shape Attributes #

All shapes share these base attributes:

Field Type Required Description
id UUID Yes Shape identifier
name string Yes Shape name
type string Yes Shape type (see above)
selrect object Yes Selection rectangle {x, y, width, height}
points array Yes Array of points [{x, y}, ...]
transform array Yes 2D transformation matrix
transformInverse array Yes Inverse transformation matrix
parentId UUID Yes Parent shape identifier
frameId UUID Yes Containing frame identifier

Geometry Attributes #

Shapes with geometry (frame, rect, circle, image, svg-raw, text):

Field Type Required Description
x number Yes X position
y number Yes Y position
width number Yes Width
height number Yes Height

Generic Attributes #

Optional attributes available on all shapes:

Field Type Description
fills array Fill styles
strokes array Stroke styles
opacity number Opacity (0-1)
blendMode string Blend mode
shadow array Shadow effects
blur object Blur effect
constraintsH string Horizontal constraint
constraintsV string Vertical constraint
r1, r2, r3, r4 number Border radius corners
blocked boolean Shape is locked
hidden boolean Shape is hidden
collapsed boolean Shape is collapsed
componentId UUID Component reference
componentFile UUID Component library file
shapeRef UUID Shape reference for components
touched array Modified component properties
interactions array Prototype interactions
exports array Export settings
grids array Grid configurations
appliedTokens object Applied design tokens
pluginData object Plugin-specific data

Type-Specific Attributes #

Frame

  • shapes: array of child shape UUIDs
  • showContent: boolean
  • hideInViewer: boolean

Group

  • shapes: array of child shape UUIDs

Bool

  • shapes: array of child shape UUIDs
  • boolType: string (union, difference, exclude, intersection)
  • content: path data

Path

  • content: path data (SVG path commands)

Text

  • content: text content with formatting
  • positionData: glyph position data

Image

  • metadata: object with width, height, mtype, id

Example Shape #

{
  "id": "260aea33-4e55-808c-8007-3d4f2efe4230",
  "name": "Rectangle",
  "type": "rect",
  "x": 100,
  "y": 100,
  "width": 200,
  "height": 150,
  "selrect": {
    "x": 100,
    "y": 100,
    "width": 200,
    "height": 150
  },
  "points": [
    {"x": 100, "y": 100},
    {"x": 300, "y": 100},
    {"x": 300, "y": 250},
    {"x": 100, "y": 250}
  ],
  "transform": [1, 0, 0, 1, 0, 0],
  "transformInverse": [1, 0, 0, 1, 0, 0],
  "parentId": "00000000-0000-0000-0000-000000000000",
  "frameId": "00000000-0000-0000-0000-000000000001",
  "fills": [
    {
      "color": "#FF5733",
      "opacity": 1
    }
  ],
  "r1": 8,
  "r2": 8,
  "r3": 8,
  "r4": 8
}

Library Assets #

Colors #

Stored at files/{file-id}/colors/{color-id}.json.

Field Type Required Description
id UUID Yes Color identifier
name string Yes Color name
path string No Path in the library tree
opacity number No Opacity (0-1)
color string Conditional Hex color (for plain colors)
gradient object Conditional Gradient definition
image object Conditional Image fill definition

Plain Color Example #

{
  "id": "abc123...",
  "name": "Primary Blue",
  "path": "Brand/Primary",
  "color": "#0066CC",
  "opacity": 1
}

Gradient Color Example #

{
  "id": "def456...",
  "name": "Sunset Gradient",
  "gradient": {
    "type": "linear",
    "startX": 0,
    "startY": 0,
    "endX": 1,
    "endY": 1,
    "stops": [
      {"color": "#FF6B6B", "offset": 0, "opacity": 1},
      {"color": "#4ECDC4", "offset": 1, "opacity": 1}
    ]
  }
}

Components #

Stored at files/{file-id}/components/{component-id}.json.

Field Type Required Description
id UUID Yes Component identifier
name string Yes Component name
path string Yes Path in the library tree
mainInstanceId UUID Yes Root shape of main instance
mainInstancePage UUID Yes Page containing main instance
modifiedAt timestamp No Last modification
objects object No Captured shapes (if deleted)

Typographies #

Stored at files/{file-id}/typographies/{typography-id}.json.

Field Type Required Description
id UUID Yes Typography identifier
name string Yes Typography name
fontId string Yes Font identifier
fontFamily string Yes Font family name
fontVariantId string Yes Font variant
fontSize string Yes Font size
fontWeight string Yes Font weight
fontStyle string Yes Font style
lineHeight string Yes Line height
letterSpacing string Yes Letter spacing
textTransform string Yes Text transform

Design Tokens #

Stored at files/{file-id}/tokens.json.

The tokens library contains:

  • Sets: Collections of tokens organized hierarchically
  • Themes: Named combinations of token sets
  • Active Themes: Currently applied themes

Token Structure #

{
  "sets": {
    "core": {
      "id": "uuid",
      "name": "Core",
      "tokens": {
        "color": {
          "primary": {
            "id": "uuid",
            "name": "primary",
            "type": "color",
            "value": "#0066CC"
          }
        }
      }
    }
  },
  "themes": {
    "light": {
      "id": "uuid",
      "name": "Light",
      "sets": ["core"]
    }
  },
  "activeThemes": ["light"]
}

Media and Storage Objects #

Storage Objects #

Binary assets (images, fonts, etc.) are stored in the objects/ directory.

Each storage object has:

  • objects/{uuid}.json - Metadata
  • objects/{uuid}.{ext} - Binary content (png, jpg, svg, etc.)

Metadata Schema #

Field Type Required Description
id UUID Yes Storage object identifier
size integer Yes File size in bytes
contentType string Yes MIME type
bucket string Yes Storage bucket
hash string No Content hash (blake2b)

Example #

{
  "id": "0039433d-adc8-430d-b2c3-d884dea6e050",
  "size": 575,
  "contentType": "image/png",
  "bucket": "file-media-object",
  "hash": "blake2b:77d447db38eb5daf31acb7344a504cacc6b79aa11855a00501d9475c595053d0"
}

Media References #

File media references are stored at files/{file-id}/media/{media-id}.json.

Field Type Required Description
id UUID Yes Media identifier
name string Yes File name
width integer Yes Image width
height integer Yes Image height
mtype string Yes MIME type
mediaId UUID Yes Reference to storage object
thumbnaillId UUID No Reference to thumbnail
isLocal boolean No Whether media is local to file

Thumbnails #

Page thumbnails are stored at files/{file-id}/thumbnails/{tag}/{page-id}/{frame-id}.json.

Field Type Required Description
fileId UUID Yes File identifier
pageId UUID Yes Page identifier
frameId UUID Yes Frame identifier
tag string Yes Thumbnail tag
mediaId UUID Yes Reference to storage object

Plugin Data #

Plugins can store custom data on files, pages, shapes, components, colors, and typographies using the pluginData field.

Structure #

{
  "pluginData": {
    "plugin-id": {
      "key1": "value1",
      "key2": "value2"
    }
  }
}

The plugin ID is a keyword (e.g., "my-plugin"), and the values are string key-value pairs.

Inspecting a .penpot File #

List Contents #

unzip -l design.penpot

Extract and View #

# Extract to temporary directory
unzip design.penpot -d /tmp/penpot-inspect

# View manifest
cat /tmp/penpot-inspect/manifest.json | jq .

# List all files
find /tmp/penpot-inspect -name "*.json" | head -20

# View a specific shape
cat /tmp/penpot-inspect/files/*/pages/*/*.json | jq .

Browser-Based Inspector #

For an interactive way to explore a .penpot file, try the Penpot file inspector. It runs entirely in your browser, displays a collapsible file tree, syntax-highlighted JSON, image previews, and clickable cross-references between shapes, components, colors, and media.

Quick Inspection Script #

#!/bin/bash
# Inspect .penpot file structure

FILE=$1
TMPDIR=$(mktemp -d)

unzip -q "$FILE" -d "$TMPDIR"

echo "=== Manifest ==="
cat "$TMPDIR/manifest.json" | jq '{type, version, files: [.files[] | {id, name}]}'

echo -e "\n=== Files ==="
for f in "$TMPDIR"/files/*.json; do
  echo "- $(jq -r '.name' "$f")"
done

echo -e "\n=== Pages ==="
for f in "$TMPDIR"/files/*/pages/*.json; do
  echo "- $(jq -r '.name' "$f")"
done

echo -e "\n=== Storage Objects ==="
ls -lh "$TMPDIR"/objects/*.{png,jpg,svg} 2>/dev/null | wc -l
echo "media files"

rm -rf "$TMPDIR"

Cross-References #

Source Code References #

The authoritative schema definitions are in the Penpot source code:

  • Manifest: backend/src/app/binfile/v3.clj (schema:manifest)
  • File: common/src/app/common/types/file.cljc (schema:file)
  • Page: common/src/app/common/types/page.cljc (schema:page)
  • Shape: common/src/app/common/types/shape.cljc (schema:shape)
  • Component: common/src/app/common/types/component.cljc (schema:component)
  • Color: common/src/app/common/types/color.cljc (schema:library-color)
  • Typography: common/src/app/common/types/typography.cljc (schema:typography)
  • Tokens: common/src/app/common/types/tokens_lib.cljc (schema:tokens-lib)
  • Plugin Data: common/src/app/common/types/plugins.cljc (schema:plugin-data)
  • Features: common/src/app/common/features.cljc (schema:features)