The migration 0032 stores every swap of a file as an override group. A swap made in a copy is paired with the child of the near main that holds the same position, as sync paired it; any other slot is dropped. All pairings are found on the data as it was, so swaps nested in swaps pair against the content of the outer one, and libraries pair the same whether they are migrated or not. A head that refers to its own slot only inherited it, and drops it even when its near main cannot be reached. Any other slot that matches no child, or whose near main is in a library that is not loaded, keeps the slot as its ref, so validation reports it. An import, which migrates its files before it links their libraries, leaves those slots and converts them once the libraries are linked. A migrated head that sits elsewhere than the child it replaces would place it gets its geometry marked as touched, so the first sync does not move it. Migrated and new files carry the feature components/swap-group, so a client that still writes slots cannot open them. Validation checks the new form: :misplaced-slot reports any slot, :misplaced-swap-group the group anywhere but on a nested copy head in a copy, :ref-not-in-near-main a nested copy head whose ref is not a child of the near main of its parent, and :duplicate-ref two children of a copy that refer to the same main shape. Each has a repair. Nothing but the migrations reads slots any more: the slot branches go from sync, swap, switch, reset, detach, paste, duplicate and move. The helpers that read and write a slot on a shape move to files/swap-slots, and the ones that follow refs to files/comp-processors. The graph projection drops the FillsSwapSlot edge, the components debugger shows the component a swapped head takes its content from, and the plugin API documents componentRefShape for a swapped copy. The swap tests are named after what they check. Benchmark (lower quantile, ms; baseline / now / ratio): deepest-edit-through-three-levels 35.2 / 34.6 / 0.98 edit-through-a-chain-of-dependents 68.9 / 63.5 / 0.92 library-update-into-copies 83.1 / 76.4 / 0.92 main-edit-into-10-copies 1.8 / 1.6 / 0.87 main-edit-into-100-copies 15.4 / 15.1 / 0.98 main-edit-into-1000-copies 153.1 / 148.8 / 0.97 variant-switch-into-copies 32.1 / 26.4 / 0.82 AI-assisted-by: claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Penpot Plugins
What can you find here?
We've been working in an MVP to allow users to develop their own plugins and use the existing ones.
There are 2 important folders to keep an eye on: apps and libs.
In the libs folder you'll find:
- plugins-runtime: here you'll find the code that initializes the plugin and sets a few listeners to know when the penpot page/file/selection changes. It has its own README.
- plugins-styles: basic css library with penpot styles in case you need help for styling your plugins.
In the apps folder you'll find some examples that use the libraries mentioned
above.
-
contrast-plugin: to run this example check Create a plugin from scratch
-
example-styles: to run this example you should run
pnpm run start:styles-example
Open in your browser: http://localhost:4202/
Run Penpot sample plugins
This guide will help you launch a Penpot plugin from the penpot-plugins repository. Before proceeding, ensure that you have Penpot running locally by following the setup instructions.
In the terminal, navigate to the penpot-plugins repository and run pnpm -r install to install the required dependencies. Then, run pnpm run start to
launch the plugins runtime.
After installing the dependencies, choose a plugin to launch. You can either run one of the provided examples or create your own (see "Creating a plugin from scratch" below). To launch a plugin, Open a new terminal tab and run the appropriate startup script for the chosen plugin.
For instance, to launch the Contrast plugin, use the following command:
// for the contrast plugin
pnpm run start:plugin:contrast
Finally, open in your browser the specific port. In this specific example would
be http://localhost:4302
A table listing the available plugins and their corresponding startup commands is provided below.
Sample plugins
| Plugin | Description | PORT | Start command | Manifest URL |
|---|---|---|---|---|
| poc-state-plugin | Sandbox plugin to test new plugins api functionality | 4202 | pnpm run start:plugin:poc-state | http://localhost:4202/assets/manifest.json |
| contrast-plugin | Sample plugin that gives you color contrast information | 4202 | pnpm run start:plugin:contrast | http://localhost:4202/assets/manifest.json |
| icons-plugin | Tool to add icons from Feather | 4202 | pnpm run start:plugin:icons | http://localhost:4202/assets/manifest.json |
| lorem-ipsum-plugin | Generate Lorem ipsum text | 4202 | pnpm run start:plugin:loremipsum | http://localhost:4202/assets/manifest.json |
| create-palette-plugin | Creates a board with all the palette colors | 4202 | pnpm run start:plugin:palette | http://localhost:4202/assets/manifest.json |
| table-plugin | Create or import table | 4202 | pnpm run start:table-plugin | http://localhost:4202/assets/manifest.json |
| rename-layers-plugin | Rename layers in bulk | 4202 | pnpm run start:plugin:renamelayers | http://localhost:4202/assets/manifest.json |
| colors-to-tokens-plugin | Generate tokens JSON file | 4202 | pnpm run start:plugin:colors-to-tokens | http://localhost:4202/assets/manifest.json |
| poc-tokens-plugin | Sandbox plugin to test tokens functionality | 4202 | pnpm run start:plugin:poc-tokens | http://localhost:4202/assets/manifest.json |
Web Apps
| App | Description | PORT | Start command | URL |
|---|---|---|---|---|
| plugins-runtime | Runtime for the plugins subsystem | 4200 | pnpm run start:app:runtime | |
| example-styles | Showcase of some of the Penpot styles that can be used in plugins | 4201 | pnpm run start:app:styles-example | http://localhost:4201/ |
Creating a plugin from scratch
If you want to create a new plugin, read the following README
License
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
Copyright (c) KALEIDOS SUBSIDIARY SL
Penpot is a Kaleidos’ open source project