Penpot, an open source interface design tool
Penpot is a browser based interface design tool whose source is open and which can run on your own server. It is developed by the Spanish company Kaleidos under the Mozilla Public License 2.0, and the repository carries over fifty eight thousand stars. The current release is 2.17.0, dated 22 July 2026.
Who this is really for
The honest answer: for teams to whom control over their data matters, not for those seeking a tool better than Figma at design work itself.
The case for this platform is clearest in three situations. The first is an organisation where designs cannot sit on somebody else's server, meaning the public sector, healthcare, defence. Running it on your own infrastructure solves a problem no closed product will solve, because none offers that option.
The second is reluctance to depend on a single vendor. Designs stored in a closed format are hostage to a vendor's pricing decisions, and the industry's experience in recent years taught many teams caution. Here files rest on open formats and can be opened outside the application itself.
The third is cost at a large team, but only in the self hosted variant. In the cloud, as you will see shortly, the free plan has limits.
If, on the other hand, you are looking for a tool where design work moves faster than in commercial products, this is not it. Penpot has closed the gap on fundamentals, but the plugin ecosystem, animation maturity, and the small conveniences of daily work still sit on the other side. This choice is made for strategic reasons rather than for comfort.
Pricing, a correction
This needs putting right, because a belief has taken hold online that Penpot is entirely free with no limits, and an earlier version of this text repeated it. The source is open and self hosting genuinely costs nothing beyond infrastructure. The cloud service, however, has plans.
| Cloud plan | Price | Scope |
|---|---|---|
| Professional | 0 USD | up to 8 team members, 10 GB storage, 7 days of version history |
| Unlimited | 7 USD per user per month | 25 GB storage, 30 days of history, bill capped at 175 USD per month |
| Enterprise | 25 USD per user per month | unlimited storage, 90 days of history, admin console, single sign on, audit logs, from 950 USD per month |
| Private server | 50,000 USD per year | dedicated infrastructure, region choice, guaranteed response times |
The eight person limit on the free plan is what most teams run into, since viewers are unlimited but designers are not. Before pricing a team at the full rate, though, check the discounts for non profits, education, and open source projects, which the vendor runs outside the price list and which you have to ask for. The cap on the paid plan at a hundred and seventy five dollars a month is also worth noting: past twenty five people the per person price starts falling, which is rare in this category.
The self hosted variant carries no licence fees. It is worth costing honestly, though, adding the server, backups, upgrades, and the time of whoever maintains it. For an eight person team the free cloud plan works out cheaper than a self hosted instance counted with labour.
The file format and what follows from it
The no lock in argument appears in every piece written about this tool, so it is worth qualifying, because it tends to be presented too optimistically.
It is true that shapes and graphics rest on open standards, so a single screen exported to a vector file opens in any graphics application. That is a genuine advantage over binary formats readable by nothing but the vendor's own software.
It is not true that an entire project is portable. Components, libraries, prototype interactions, and dependencies between files are structures specific to this application. Opening an export elsewhere gives you graphics, not a working design system with its relationships intact.
The practical conclusion is that openness protects you against losing access to content rather than against the cost of migration. That is still more than most competitors offer, but it is worth knowing exactly what you are counting on.
There is a second side to that openness, mentioned less often and useful day to day. Since the graphics rest on web standards, export goes straight to a format you drop into a page, with no intermediate conversion step. On icons and simple illustrations that removes a little friction between design and implementation, since the developer receives a file ready to use rather than something that first has to pass through an export tool.
Do bear in mind, though, that files leaving design tools are rarely optimised. They carry metadata, excess coordinate precision, and groups adding nothing, so before deployment they pass through an optimiser anyway. That is a small thing, but it returns on every project, and setting it up once in the build process beats doing it by hand for every icon.
Why Penpot?
Key advantages
- Open source - Repository publicly available under the Mozilla Public License 2.0
- Self hosting - Can run on your own infrastructure with no licence fees
- Browser based - Works in any browser without installation
- Open formats - Graphics built on standards rather than a binary format
- Real time collaboration - Several people in one file
- Platform independence - Windows, macOS, and Linux through a browser
- Data control - With a self hosted instance, data never leaves the organisation
Penpot vs Figma vs Sketch vs Adobe XD
| Feature | Penpot | Figma | Sketch | Adobe XD |
|---|---|---|---|---|
| Price | free up to 8 people, then from 7 USD | free tier plus subscription | subscription | product discontinued |
| Open source | yes, MPL 2.0 | no | no | no |
| Self hosting | yes | no | no | no |
| Runs in a browser | yes | yes | no, macOS only | no |
| Open graphics format | yes | export only | export only | export only |
| Plugins | few | a great many | many | discontinued |
| Flexible layouts | yes, built on the CSS model | yes | yes | not applicable |
| Works offline | yes, on your own server | no | yes | yes |
Installation and getting started
Option 1: Penpot Cloud (fastest)
# Just go to the website
https://design.penpot.app
# Register a free account
# Done - you can start designing!Option 2: Self-hosting with Docker
# Clone the official repository
git clone https://github.com/penpot/penpot.git
cd penpot/docker/images
# Start using Docker Compose
docker-compose -f docker-compose.yaml up -d
# Penpot will be available at
# http://localhost:9001Docker Compose configuration
# docker-compose.yaml
version: "3.5"
services:
penpot-frontend:
image: "penpotapp/frontend:latest"
restart: always
ports:
- 9001:80
volumes:
- penpot_assets_data:/opt/data/assets
depends_on:
- penpot-backend
- penpot-exporter
environment:
- PENPOT_FLAGS=enable-registration enable-login-with-password
penpot-backend:
image: "penpotapp/backend:latest"
restart: always
volumes:
- penpot_assets_data:/opt/data/assets
depends_on:
- penpot-postgres
- penpot-redis
environment:
- PENPOT_FLAGS=enable-registration enable-login-with-password disable-email-verification
- PENPOT_PUBLIC_URI=http://localhost:9001
- PENPOT_DATABASE_URI=postgresql://penpot-postgres/penpot
- PENPOT_DATABASE_USERNAME=penpot
- PENPOT_DATABASE_PASSWORD=penpot
- PENPOT_REDIS_URI=redis://penpot-redis/0
- PENPOT_ASSETS_STORAGE_BACKEND=assets-fs
- PENPOT_STORAGE_ASSETS_FS_DIRECTORY=/opt/data/assets
penpot-exporter:
image: "penpotapp/exporter:latest"
restart: always
environment:
- PENPOT_PUBLIC_URI=http://penpot-frontend
penpot-postgres:
image: "postgres:15"
restart: always
stop_signal: SIGINT
volumes:
- penpot_postgres_v15:/var/lib/postgresql/data
environment:
- POSTGRES_INITDB_ARGS=--data-checksums
- POSTGRES_DB=penpot
- POSTGRES_USER=penpot
- POSTGRES_PASSWORD=penpot
penpot-redis:
image: redis:7
restart: always
volumes:
penpot_postgres_v15:
penpot_assets_data:Option 3: installation on Kubernetes
# penpot-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: penpot
namespace: design-tools
spec:
replicas: 1
selector:
matchLabels:
app: penpot
template:
metadata:
labels:
app: penpot
spec:
containers:
- name: penpot-frontend
image: penpotapp/frontend:latest
ports:
- containerPort: 80
env:
- name: PENPOT_FLAGS
value: "enable-registration enable-login-with-password"
- name: penpot-backend
image: penpotapp/backend:latest
env:
- name: PENPOT_PUBLIC_URI
value: "https://penpot.yourdomain.com"
- name: PENPOT_DATABASE_URI
valueFrom:
secretKeyRef:
name: penpot-secrets
key: database-uri
---
apiVersion: v1
kind: Service
metadata:
name: penpot-service
namespace: design-tools
spec:
selector:
app: penpot
ports:
- port: 80
targetPort: 80
type: LoadBalancerMain Penpot features
1. Vector editing tools
Penpot offers a full set of vector tools:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Shape Tools β
β βββ Rectangle (R) β
β βββ Ellipse (E) β
β βββ Polygon β
β βββ Star β
β β
β Drawing Tools β
β βββ Pen Tool (P) - Bezier curves β
β βββ Pencil Tool - Freehand drawing β
β βββ Path editing β
β β
β Boolean Operations β
β βββ Union - Merge shapes β
β βββ Difference - Subtract β
β βββ Intersection - Common area β
β βββ Exclusion - Exclude overlap β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ2. Flex Layout (auto-layout)
Penpot introduces Flex Layout inspired by CSS Flexbox:
/* CSS equivalent of Penpot Flex Layout */
.flex-container {
display: flex;
flex-direction: row | column;
justify-content: flex-start | center | flex-end | space-between | space-around;
align-items: flex-start | center | flex-end | stretch;
gap: 16px;
padding: 24px;
}
/* In Penpot you set this through the UI:
1. Select the container
2. Design panel > Layout > Flex
3. Set Direction, Alignment, Gap, Padding
*/Practical example:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CARD COMPONENT with Flex Layout β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββ β
β β [Image] β β
β β β β
β β βββββββββββββββββββββββββββββββββββββββββββ β β
β β β Title [Icon] β β β
β β β Description text that can wrap to β β β
β β β multiple lines automatically β β β
β β β β β β
β β β [Button] [Button] β β β
β β βββββββββββββββββββββββββββββββββββββββββββ β β
β βββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Flex structure: β
β - Main container: Column, gap: 16px β
β - Header: Row, space-between β
β - Buttons: Row, gap: 8px, align-end β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ3. Components and instances
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β COMPONENT SYSTEM β
β β
β 1. Create Main Component: β
β - Select elements β
β - Ctrl/Cmd + K or right-click > Create Componentβ
β β
β 2. Use instances: β
β - Drag from Assets panel β
β - Or Ctrl/Cmd + D to duplicate β
β β
β 3. Edit Main Component: β
β - Changes propagate to all instances β
β β
β 4. Override in instance: β
β - You can override text, colors, images β
β - Reset override: right-click > Reset β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ4. Design Tokens and styles
/* Penpot supports global styles for: */
/* Colors */
--color-primary: #3366FF;
--color-secondary: #6B7280;
--color-success: #10B981;
--color-error: #EF4444;
/* Typography */
--font-heading: Inter, 700, 32px;
--font-body: Inter, 400, 16px;
--font-caption: Inter, 400, 12px;
/* Shadows */
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
--shadow-md: 0 4px 6px rgba(0,0,0,0.1);
--shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
/* In Penpot:
1. Design panel > Fill/Stroke > + Add to library
2. Name the style
3. Use in other elements via Assets panel
*/5. Interactive prototyping
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PROTOTYPING INTERACTIONS β
β β
β Available triggers: β
β βββ On Click β
β βββ Mouse Enter (Hover) β
β βββ Mouse Leave β
β βββ After Delay β
β β
β Available actions: β
β βββ Navigate To - go to another page β
β βββ Open Overlay - open popup/modal β
β βββ Close Overlay - close overlay β
β βββ Previous Page - go back β
β βββ Open URL - open external link β
β β
β Transition animations: β
β βββ Dissolve - smooth fade β
β βββ Slide - sliding motion β
β β βββ Right, Left, Up, Down β
β βββ Push - pushing transition β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββExample of creating a prototype:
Scenario: Login Flow
[Login Screen] ββClick "Sign In"ββ> [Dashboard]
β
βββClick "Forgot Password"ββ> [Reset Password]
β
Click "Send"
β
v
[Confirmation Modal]
β
After 3s / Click
β
v
[Login Screen]6. Grid system and guides
/* Penpot supports various grid types */
/* Layout Grid - for responsive design */
.layout-grid {
columns: 12;
gutter: 24px;
margin: auto | fixed;
type: stretch | center | left | right;
}
/* Square Grid - for pixel-perfect design */
.square-grid {
size: 8px;
color: rgba(0, 0, 0, 0.1);
}
/* Custom Guides */
.guides {
horizontal: 64px, 128px, 512px;
vertical: 50%, 100%;
}7. Export options
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β EXPORT FORMATS β
β β
β Images: β
β βββ PNG - with transparency β
β βββ JPEG - for photos β
β βββ SVG - vectors (native format!) β
β βββ PDF - for documentation β
β β
β Scale options: β
β βββ 1x - standard β
β βββ 2x - retina β
β βββ 3x - high DPI β
β βββ Custom - e.g. 0.5x, 4x β
β β
β Full project export: β
β - File > Export project (.penpot) β
β - Includes all pages, components, assets β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββCSS code generation
Penpot automatically generates CSS code for selected elements:
/* Example of generated CSS for a button */
.button {
/* Layout */
display: flex;
align-items: center;
justify-content: center;
padding: 12px 24px;
gap: 8px;
/* Appearance */
background: #3366FF;
border-radius: 8px;
/* Typography */
font-family: 'Inter', sans-serif;
font-weight: 600;
font-size: 16px;
line-height: 24px;
color: #FFFFFF;
/* Effects */
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
}
/* Hover state (from prototype) */
.button:hover {
background: #2952CC;
transform: translateY(-1px);
box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.15);
}Inspect panel - code generation
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β INSPECT MODE β
β β
β 1. Enable Inspect mode (code icon in toolbar) β
β 2. Click any element β
β 3. View the generated code: β
β β
β Tabs: β
β βββ Info - dimensions, position β
β βββ Design - CSS styles β
β βββ Code - full CSS/SVG β
β β
β Copying: β
β - Click to copy individual properties β
β - "Copy all" for full CSS β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββTeam collaboration
Real-time collaboration
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β COLLABORATION FEATURES β
β β
β Multi-cursor editing β
β βββ See other users' cursors β
β βββ Colored avatars next to selections β
β βββ Live preview of changes β
β β
β Comments β
β βββ Click anywhere + C to add comment β
β βββ Thread replies β
β βββ Resolve/Unresolve β
β βββ Mentions @username β
β β
β Sharing β
β βββ View link - view only β
β βββ Edit link - full editing β
β βββ Prototype link - interactive prototype β
β β
β Team Libraries β
β βββ Shared components β
β βββ Shared styles (colors, typography) β
β βββ Sync across projects β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββVersion history
Version history in Penpot:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FILE > Version History β
β β
β Today β
β βββ 14:32 - Jan updated Button component β
β βββ 13:15 - Maria added new page β
β βββ 11:00 - Auto-save β
β β
β Yesterday β
β βββ 18:45 - Jan renamed project β
β βββ 09:30 - Initial version β
β β
β Actions: β
β - Preview any version β
β - Restore to previous version β
β - Create named snapshot β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββPlugins and extensions
Penpot is actively developing its plugin system:
Available plugins (2024+)
// Example Penpot plugin structure
// penpot-plugin-example/manifest.json
{
"name": "My Penpot Plugin",
"version": "1.0.0",
"description": "Example plugin for Penpot",
"main": "index.js",
"permissions": [
"selection:read",
"selection:write",
"file:read",
"file:write"
]
}
// penpot-plugin-example/index.js
penpot.ui.open("My Plugin", `
<div style="padding: 16px;">
<h2>My Plugin</h2>
<button onclick="applyColors()">Apply Brand Colors</button>
</div>
`);
async function applyColors() {
const selection = await penpot.selection.get();
for (const shape of selection) {
await penpot.shape.update(shape.id, {
fill: { color: "#3366FF" }
});
}
}Plugin ideas
Popular plugin types:
βββ Content generators (Lorem ipsum, avatars, data)
βββ Design tokens import/export
βββ Accessibility checkers
βββ Icon libraries
βββ Chart generators
βββ Code export (Tailwind, CSS-in-JS)
βββ Design system documentation
βββ Integration with dev toolsIntegrations
Git integration
# Export project to SVG and version with Git
penpot-cli export --project "My Project" --format svg --output ./designs
# File structure
designs/
βββ page-1/
β βββ frame-login.svg
β βββ frame-dashboard.svg
β βββ components/
β βββ button.svg
β βββ card.svg
βββ page-2/
β βββ ...
βββ tokens.jsonWebhooks
// Webhook configuration (self-hosted)
// config.edn
{:webhooks
{:events #{:file-change :comment-created :member-joined}
:url "https://your-server.com/penpot-webhook"
:secret "your-webhook-secret"}}
// Webhook handler
app.post('/penpot-webhook', (req, res) => {
const { event, payload } = req.body;
switch (event) {
case 'file-change':
console.log(`File ${payload.file_id} was modified`);
// Trigger CI/CD pipeline
break;
case 'comment-created':
// Notify on Slack
break;
}
res.status(200).send('OK');
});API access (self-hosted)
# Python SDK for Penpot API
import requests
class PenpotAPI:
def __init__(self, base_url, token):
self.base_url = base_url
self.headers = {"Authorization": f"Bearer {token}"}
def get_projects(self):
response = requests.get(
f"{self.base_url}/api/rpc/command/get-all-projects",
headers=self.headers
)
return response.json()
def export_file(self, file_id, format="svg"):
response = requests.post(
f"{self.base_url}/api/export",
headers=self.headers,
json={
"file_id": file_id,
"format": format,
"scale": 1
}
)
return response.content
# Usage
api = PenpotAPI("https://your-penpot.com", "your-api-token")
projects = api.get_projects()
svg_data = api.export_file("file-uuid", "svg")Design system in Penpot
Creating a design system
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DESIGN SYSTEM STRUCTURE β
β β
β Design System Project β
β βββ Foundations β
β β βββ Colors β
β β β βββ Primary palette β
β β β βββ Neutral palette β
β β β βββ Semantic colors β
β β β βββ Gradients β
β β βββ Typography β
β β β βββ Headings (H1-H6) β
β β β βββ Body text β
β β β βββ UI text β
β β βββ Spacing β
β β β βββ 4px, 8px, 12px, 16px, 24px, 32px... β
β β βββ Shadows β
β β βββ Border radius β
β β β
β βββ Components β
β β βββ Buttons β
β β β βββ Primary / Secondary / Ghost β
β β β βββ Small / Medium / Large β
β β β βββ States: Default, Hover, Active, Disabledβ
β β βββ Inputs β
β β βββ Cards β
β β βββ Navigation β
β β βββ Modals β
β β β
β βββ Patterns β
β βββ Forms β
β βββ Tables β
β βββ Page layouts β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββShared libraries
Sharing a Design System across projects:
1. Publish the library:
File > Publish as Shared Library
2. Use in another project:
Assets Panel > Libraries > + Add library
3. Synchronization:
- Make changes in the source library
- Assets Panel > Update available
- Review changes > UpdateKeyboard shortcuts
Essential shortcuts
| Action | Shortcut |
|---|---|
| Move tool | V |
| Rectangle | R |
| Ellipse | E |
| Frame | F |
| Text | T |
| Pen tool | P |
| Comments | C |
| Zoom in/out | Cmd/Ctrl + +/- |
| Zoom to fit | Cmd/Ctrl + 1 |
| Zoom to selection | Cmd/Ctrl + 2 |
| Pan | Space + drag |
| Duplicate | Cmd/Ctrl + D |
| Group | Cmd/Ctrl + G |
| Ungroup | Cmd/Ctrl + Shift + G |
| Create component | Cmd/Ctrl + K |
| Copy/Paste | Cmd/Ctrl + C/V |
| Undo/Redo | Cmd/Ctrl + Z / Shift + Z |
| Hide/Show UI | Cmd/Ctrl + \ |
| Present prototype | Cmd/Ctrl + Enter |
Migrating from Figma to Penpot
Exporting from Figma
1. In Figma:
- Select a frame or the entire page
- File > Export
- Choose SVG format
- Check "Include 'id' attribute"
2. In Penpot:
- File > Import
- Select the exported SVG files
- Adjust the imported elementsMigration limitations
What transfers well:
Vector shapes
Text (basic)
Colors and gradients
Effects (shadow, blur)
Grouping
What requires manual work:
Note: Auto-layout to Flex Layout (manual configuration)
Note: Components (need to be recreated)
Note: Prototyping (needs to be recreated)
Note: Plugins (no equivalents)
Note: Variants (in development in Penpot)The import tool
Migration goes through an official plugin run on the Figma side, which packs a design into a file Penpot accepts. There is no command line tool doing the same, so the export step is performed by hand inside Figma.
1. Install the Penpot exporter plugin in Figma
2. Run it on the file you want to move
3. Download the generated .penpot file
4. In Penpot choose import and point at the downloaded fileThe plugin's code sits in the penpot-exporter-figma-plugin repository, so before migrating a large project it pays to read the open issues and check whether any of them concerns the features you use.
What is missing against the competition
This section is usually skipped in articles like this, and it is the one that most helps a decision.
Plugins are the largest gap. The competition holds an ecosystem numbering in the thousands, from placeholder content generators to accessibility checkers. Penpot supports plugins, but their number is disproportionately smaller, and many daily conveniences have to be done by hand.
The second matter is prototyping. Basic transitions between screens work, while richer interactions, animated component states, and variable driven behaviour are thinner here. Enough to present a flow, not necessarily enough to show micro interactions to a client.
The third is performance on large files, as in other browser based tools such as Figma. The application runs in a browser, and a project with hundreds of screens can slow down more than is acceptable. Splitting work across several files helps and is a necessity here rather than a preference.
The fourth is availability of people who know the tool. Hiring a designer, you will find dozens of candidates working in commercial products and a handful who know this one. Learning the basics is quick, since the concepts are similar, but it is still a cost to count.
The fifth is handing designs outside your team. If you work with an agency or a client using a different tool, exchanging files becomes a problem. Import from competing formats exists but reconstructs graphics rather than components and prototypes, so part of the work has to be redone.
FAQ
Is Penpot really free?
The source is open, and self hosting carries no licence fees. The cloud service does have plans: the free one covers up to eight team members and ten gigabytes of storage, and past that you pay per person.
Can I work without network access?
Not in the cloud. With a self hosted instance yes, provided the server sits on your local network, since the application runs in a browser and needs to reach a server regardless.
Can I import designs from Figma?
Only partially. Graphics transfer through a vector format, but components, libraries, and prototypes have to be rebuilt by hand, since those are structures specific to each application.
Do plugins from competing tools work?
No. Penpot has its own plugin system and is not compatible with other programs' extensions. The number of available add ons is also markedly smaller than the competition's.
When does self hosting beat the cloud?
Usually only once the team exceeds the free plan's limit and you require that data not leave the organisation. For a small team without that requirement, the cost of maintaining a server exceeds the subscription saving.
Common deployment mistakes
The first is treating self hosting as a one off task. The application comprises several services, a database, and file storage, so upgrades, backups, and monitoring become somebody's responsibility. If nobody takes that on, six months later you are running a version with unpatched bugs.
The second is skipping backups of the file storage. The database alone is not enough, because images and assets sit separately, and restoring a project without them leaves empty frames where the graphics were.
The third is migrating the whole team at once. It is wiser to start with one project, check whether the missing features genuinely impede your work, and only then decide about the rest.
The fourth is keeping everything in one file. The application runs in a browser and slows on large projects, so splitting by topic is a practical necessity here rather than a matter of tidiness.
The fifth is assuming developer handoff looks the same as in the tool you came from. An inspection mode with specifications exists, but treat generated code as a reference for values rather than something to paste into a Tailwind CSS or React project.
The source and releases live in the Penpot repository, and current plans on the pricing page.