A swapped copy sub-head now keeps the shape-ref of the main child it replaces (its position), takes its content from its own component, and carries the touched group :swap-group. It used to point at the root of the new component and store a swap slot naming the replaced child. Every path reads and writes that form: - sync pairs a swapped head with the child it replaces and syncs it from its own component; it takes from the replaced child only its placement: position, constraints and layout item attributes; - reset undoes a swap in place, keeping the head's id and the other overrides of the copy; - detach, paste and duplicate make a head that leaves every copy level a plain copy of its own component, and advance a deeper one by position; the children of a swapped head never advance; - a variant switch keeps a swap stored this way, and counts only the copy's own swap, not one made in a main of the chain; - update main replaces the main child with a clone of the swapped one, and from a swapped head updates its own component; - a swap inside a copy keeps the old shape-ref and adds :swap-group; swapping back to the component of that position gives a plain nested copy whose children refer to the position's children; a swap inside a main is a plain nested copy. Files that hold swap slots keep working until a migration converts them. The component memories describe the model. This fixes what came from the slot: reset of a swapped child cleared the other overrides of the copy (F12) and gave copies of a main new ids (F66); update main left a swap mark (F16); a second variant switch lost the overrides (F29); grid cells did not pair a swapped child (F44); a swapped child did not follow its position (F65). F49 keeps failing, in another form. The tests that asserted slots now assert the override group; the tests of the slot code build the old form with :as-slot?. Benchmark (lower quantile, ms; baseline / now / ratio): deepest-edit-through-three-levels 35.2 / 35.4 / 1.01 edit-through-a-chain-of-dependents 68.9 / 68.7 / 1.00 library-update-into-copies 83.1 / 77.5 / 0.93 main-edit-into-10-copies 1.8 / 1.6 / 0.92 main-edit-into-100-copies 15.4 / 15.4 / 1.00 main-edit-into-1000-copies 153.1 / 151.1 / 0.99 variant-switch-into-copies 32.1 / 32.4 / 1.01 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