Penpot UI/UX Design Guide
Create professional, user-centered designs in Penpot using the penpot/penpot-mcp MCP server and proven UI/UX principles.
Available MCP Tools
| Tool |
Purpose |
mcp__penpot__execute_code |
Run JavaScript in Penpot plugin context to create/modify designs |
mcp__penpot__export_shape |
Export shapes as PNG/SVG for visual inspection |
mcp__penpot__import_image |
Import images (icons, photos, logos) into designs |
mcp__penpot__penpot_api_info |
Retrieve Penpot API documentation |
MCP Server Setup
The Penpot MCP tools require the penpot/penpot-mcp server running locally. For detailed installation and troubleshooting, see setup-troubleshooting.md.
Before Setup: Check If Already Running
Always check if the MCP server is already available before attempting setup:
Try calling a tool first: Attempt mcp__penpot__penpot_api_info - if it succeeds, the server is running and connected. No setup needed.
If the tool fails, ask the user:
"The Penpot MCP server doesn't appear to be connected. Is the server already installed and running? If so, I can help troubleshoot. If not, I can guide you through the setup."
Only proceed with setup instructions if the user confirms the server is not installed.
Quick Start (Only If Not Installed)
# Clone and install
git clone https://github.com/penpot/penpot-mcp.git
cd penpot-mcp
npm install
# Build and start servers
npm run bootstrap
Then in Penpot:
- Open a design file
- Go to Plugins → Load plugin from URL
- Enter:
http://localhost:4400/manifest.json
- Click "Connect to MCP server" in the plugin UI
VS Code Configuration
Add to settings.json:
{
"mcp": {
"servers": {
"penpot": {
"url": "http://localhost:4401/sse"
}
}
}
}
Troubleshooting (If Server Is Installed But Not Working)
| Issue |
Solution |
| Plugin won't connect |
Check servers are running (npm run start:all in penpot-mcp dir) |
| Browser blocks localhost |
Allow local network access prompt, or disable Brave Shield, or try Firefox |
| Tools not appearing in client |
Restart VS Code/Claude completely after config changes |
| Tool execution fails/times out |
Ensure Penpot plugin UI is open and shows "Connected" |
| "WebSocket connection failed" |
Check firewall allows ports 4400, 4401, 4402 |
Quick Reference
| Task |
Reference File |
| MCP server installation & troubleshooting |
setup-troubleshooting.md |
| Component specs (buttons, forms, nav) |
component-patterns.md |
| Accessibility (contrast, touch targets) |
accessibility.md |
| Screen sizes & platform specs |
platform-guidelines.md |
Core Design Principles
The Golden Rules
- Clarity over cleverness: Every element must have a purpose
- Consistency builds trust: Reuse patterns, colors, and components
- User goals first: Design for tasks, not features
- Accessibility is not optional: Design for everyone
- Test with real users: Validate assumptions early
Visual Hierarchy (Priority Order)
- Size: Larger = more important
- Color/Contrast: High contrast draws attention
- Position: Top-left (LTR) gets seen first
- Whitespace: Isolation emphasizes importance
- Typography weight: Bold stands out
Design Workflow
- Check for design system first: Ask user if they have existing tokens/specs, or discover from current Penpot file
- Understand the page: Call
mcp__penpot__execute_code with penpotUtils.shapeStructure() to see hierarchy
- Find elements: Use
penpotUtils.findShapes() to locate elements by type or name
- Create/modify: Use
penpot.createBoard(), penpot.createRectangle(), penpot.createText() etc.
- Apply layout: Use
addFlexLayout() for responsive containers
- Validate: Call
mcp__penpot__export_shape to visually check your work
Design System Handling
Before creating designs, determine if the user has an existing design system:
- Ask the user: "Do you have a design system or brand guidelines to follow?"
- Discover from Penpot: Check for existing components, colors, and patterns
// Discover existing design patterns in current file
const allShapes = penpotUtils.findShapes(() => true, penpot.root);
// Find existing colors in use
const colors = new Set();
allShapes.forEach(s => {
if (s.fills) s.fills.forEach(f => colors.add(f.fillColor));
});
// Find existing text styles (font sizes, weights)
const textStyles = allShapes
.filter(s => s.type === 'text')
.map(s => ({ fontSize: s.fontSize, fontWeight: s.fontWeight }));
// Find existing components
const components = penpot.library.local.components;
return { colors: [...colors], textStyles, componentCount: components.length };
If user HAS a design system:
- Use their specified colors, spacing, typography
- Match their existing component patterns
- Follow their naming conventions
If user has NO design system:
- Use the default tokens below as a starting point
- Offer to help establish consistent patterns
- Reference specs in component-patterns.md
Key Penpot API Gotchas
width/height are READ-ONLY → use shape.resize(w, h)
parentX/parentY are READ-ONLY → use penpotUtils.setParentXY(shape, x, y)
- Use
insertChild(index, shape) for z-ordering (not appendChild)
- Flex children array order is REVERSED for
dir="column" or dir="row"
- After
text.resize(), reset growType to "auto-width" or "auto-height"
Positioning New Boards
Always check existing boards before creating new ones to avoid overlap:
// Find all existing boards and calculate next position
const boards = penpotUtils.findShapes(s => s.type === 'board', penpot.root);
let nextX = 0;
const gap = 100; // Space between boards
if (boards.length > 0) {
// Find rightmost board edge
boards.forEach(b => {
const rightEdge = b.x + b.width;
if (rightEdge + gap > nextX) {
nextX = rightEdge + gap;
}
});
}
// Create new board at calculated position
const newBoard = penpot.createBoard();
newBoard.x = nextX;
newBoard.y = 0;
newBoard.resize(375, 812);
Board spacing guidelines:
- Use 100px gap between related screens (same flow)
- Use 200px+ gap between different sections/flows
- Align boards vertically (same y) for visual organization
- Group related screens horizontally in user flow order
Default Design Tokens
Use these defaults only when user has no design system. Always prefer user's tokens if available.
Spacing Scale (8px base)
| Token |
Value |
Usage |
spacing-xs |
4px |
Tight inline elements |
spacing-sm |
8px |
Related elements |
spacing-md |
16px |
Default padding |
spacing-lg |
24px |
Section spacing |
spacing-xl |
32px |
Major sections |
spacing-2xl |
48px |
Page-level spacing |
Typography Scale
| Level |
Size |
Weight |
Usage |
| Display |
48-64px |
Bold |
Hero headlines |
| H1 |
32-40px |
Bold |
Page titles |
| H2 |
24-28px |
Semibold |
Section headers |
| H3 |
20-22px |
Semibold |
Subsections |
| Body |
16px |
Regular |
Main content |
| Small |
14px |
Regular |
Secondary text |
| Caption |
12px |
Regular |
Labels, hints |
Color Usage
| Purpose |
Recommendation |
| Primary |
Main brand color, CTAs |
| Secondary |
Supporting actions |
| Success |
#22C55E range (confirmations) |
| Warning |
#F59E0B range (caution) |
| Error |
#EF4444 range (errors) |
| Neutral |
Gray scale for text/borders |
Common Layouts
Mobile Screen (375×812)
┌─────────────────────────────┐
│ Status Bar (44px) │
├─────────────────────────────┤
│ Header/Nav (56px) │
├─────────────────────────────┤
│ │
│ Content Area │
│ (Scrollable) │
│ Padding: 16px horizontal │
│ │
├─────────────────────────────┤
│ Bottom Nav/CTA (84px) │
└─────────────────────────────┘
Desktop Dashboard (1440×900)
┌──────┬──────────────────────────────────┐
│ │ Header (64px) │
│ Side │──────────────────────────────────│
│ bar │ Page Title + Actions │
│ │──────────────────────────────────│
│ 240 │ Content Grid │
│ px │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ │Card │ │Card │ │Card │ │Card │ │
│ │ └─────┘ └─────┘ └─────┘ └─────┘ │
│ │ │
└──────┴──────────────────────────────────┘
Component Checklist
Buttons
Forms
Navigation
Accessibility Quick Checks
- Color contrast: Text 4.5:1, Large text 3:1
- Touch targets: Minimum 44×44px
- Focus states: Visible keyboard focus indicators
- Alt text: Meaningful descriptions for images
- Hierarchy: Proper heading levels (H1→H2→H3)
- Color independence: Never rely solely on color
Design Review Checklist
Before finalizing any design:
Validating Designs
Use these validation approaches with mcp__penpot__execute_code:
| Check |
Method |
| Elements outside bounds |
penpotUtils.analyzeDescendants() with isContainedIn() |
| Text too small (<12px) |
penpotUtils.findShapes() filtering by fontSize |
| Missing contrast |
Call mcp__penpot__export_shape and visually inspect |
| Hierarchy structure |
penpotUtils.shapeStructure() to review nesting |
Export CSS
Use penpot.generateStyle(selection, { type: 'css', includeChildren: true }) via mcp__penpot__execute_code to extract CSS from designs.
Tips for Great Designs
- Start with content: Real content reveals layout needs
- Design mobile-first: Constraints breed creativity
- Use a grid: 8px base grid keeps things aligned
- Limit colors: 1 primary + 1 secondary + neutrals
- Limit fonts: 1-2 typefaces maximum
- Embrace whitespace: Breathing room improves comprehension
- Be consistent: Same action = same appearance everywhere
- Provide feedback: Every action needs a response
1---2name: sample-awesome-penpot-uiux-design3description: Comprehensive guide for creating professional UI/UX designs in Penpot using MCP tools. Use this skill when: (1) Creating new UI/UX designs for web, mobile, or desktop applications, (2) Building design systems with components and tokens, (3) Designing dashboards, forms, navigation, or landing pages, (4) Applying accessibility standards and best practices, (5) Following platform guidelines (iOS, Android, Material Design), (6) Reviewing or improving existing Penpot designs for usability. Triggers: "design a UI", "create interface", "build layout", "design dashboard", "create form", "design landing page", "make it accessible", "design system", "component library".4---5
6# Penpot UI/UX Design Guide
7
8Create professional, user-centered designs in Penpot using the `penpot/penpot-mcp` MCP server and proven UI/UX principles.
9
10## Available MCP Tools
11
12| Tool | Purpose |
13| ---- | ------- |
14| `mcp__penpot__execute_code` | Run JavaScript in Penpot plugin context to create/modify designs |
15| `mcp__penpot__export_shape` | Export shapes as PNG/SVG for visual inspection |
16| `mcp__penpot__import_image` | Import images (icons, photos, logos) into designs |
17| `mcp__penpot__penpot_api_info` | Retrieve Penpot API documentation |
18
19## MCP Server Setup
20
21The Penpot MCP tools require the `penpot/penpot-mcp` server running locally. For detailed installation and troubleshooting, see [setup-troubleshooting.md](references/setup-troubleshooting.md).
22
23### Before Setup: Check If Already Running
24
25**Always check if the MCP server is already available before attempting setup:**
26
271. **Try calling a tool first**: Attempt `mcp__penpot__penpot_api_info` - if it succeeds, the server is running and connected. No setup needed.
28
292. **If the tool fails**, ask the user:
30 > "The Penpot MCP server doesn't appear to be connected. Is the server already installed and running? If so, I can help troubleshoot. If not, I can guide you through the setup."
31
323. **Only proceed with setup instructions if the user confirms the server is not installed.**
33
34### Quick Start (Only If Not Installed)
35
36```bash
37# Clone and install
38git clone https://github.com/penpot/penpot-mcp.git
39cd penpot-mcp
40npm install
41
42# Build and start servers
43npm run bootstrap
44```
45
46Then in Penpot:
471. Open a design file
482. Go to **Plugins** → **Load plugin from URL**
493. Enter: `http://localhost:4400/manifest.json`
504. Click **"Connect to MCP server"** in the plugin UI
51
52### VS Code Configuration
53
54Add to `settings.json`:
55```json
56{
57 "mcp": {
58 "servers": {
59 "penpot": {
60 "url": "http://localhost:4401/sse"
61 }
62 }
63 }
64}
65```
66
67### Troubleshooting (If Server Is Installed But Not Working)
68
69| Issue | Solution |
70| ----- | -------- |
71| Plugin won't connect | Check servers are running (`npm run start:all` in penpot-mcp dir) |
72| Browser blocks localhost | Allow local network access prompt, or disable Brave Shield, or try Firefox |
73| Tools not appearing in client | Restart VS Code/Claude completely after config changes |
74| Tool execution fails/times out | Ensure Penpot plugin UI is open and shows "Connected" |
75| "WebSocket connection failed" | Check firewall allows ports 4400, 4401, 4402 |
76
77## Quick Reference
78
79| Task | Reference File |
80| ---- | -------------- |
81| MCP server installation & troubleshooting | [setup-troubleshooting.md](references/setup-troubleshooting.md) |
82| Component specs (buttons, forms, nav) | [component-patterns.md](references/component-patterns.md) |
83| Accessibility (contrast, touch targets) | [accessibility.md](references/accessibility.md) |
84| Screen sizes & platform specs | [platform-guidelines.md](references/platform-guidelines.md) |
85
86## Core Design Principles
87
88### The Golden Rules
89
901. **Clarity over cleverness**: Every element must have a purpose
912. **Consistency builds trust**: Reuse patterns, colors, and components
923. **User goals first**: Design for tasks, not features
934. **Accessibility is not optional**: Design for everyone
945. **Test with real users**: Validate assumptions early
95
96### Visual Hierarchy (Priority Order)
97
981. **Size**: Larger = more important
992. **Color/Contrast**: High contrast draws attention
1003. **Position**: Top-left (LTR) gets seen first
1014. **Whitespace**: Isolation emphasizes importance
1025. **Typography weight**: Bold stands out
103
104## Design Workflow
105
1061. **Check for design system first**: Ask user if they have existing tokens/specs, or discover from current Penpot file
1072. **Understand the page**: Call `mcp__penpot__execute_code` with `penpotUtils.shapeStructure()` to see hierarchy
1083. **Find elements**: Use `penpotUtils.findShapes()` to locate elements by type or name
1094. **Create/modify**: Use `penpot.createBoard()`, `penpot.createRectangle()`, `penpot.createText()` etc.
1105. **Apply layout**: Use `addFlexLayout()` for responsive containers
1116. **Validate**: Call `mcp__penpot__export_shape` to visually check your work
112
113## Design System Handling
114
115**Before creating designs, determine if the user has an existing design system:**
116
1171. **Ask the user**: "Do you have a design system or brand guidelines to follow?"
1182. **Discover from Penpot**: Check for existing components, colors, and patterns
119
120```javascript
121// Discover existing design patterns in current file
122const allShapes = penpotUtils.findShapes(() => true, penpot.root);
123
124// Find existing colors in use
125const colors = new Set();
126allShapes.forEach(s => {
127 if (s.fills) s.fills.forEach(f => colors.add(f.fillColor));
128});
129
130// Find existing text styles (font sizes, weights)
131const textStyles = allShapes
132 .filter(s => s.type === 'text')
133 .map(s => ({ fontSize: s.fontSize, fontWeight: s.fontWeight }));
134
135// Find existing components
136const components = penpot.library.local.components;
137
138return { colors: [...colors], textStyles, componentCount: components.length };
139```
140
141**If user HAS a design system:**
142
143- Use their specified colors, spacing, typography
144- Match their existing component patterns
145- Follow their naming conventions
146
147**If user has NO design system:**
148
149- Use the default tokens below as a starting point
150- Offer to help establish consistent patterns
151- Reference specs in [component-patterns.md](references/component-patterns.md)
152
153## Key Penpot API Gotchas
154
155- `width`/`height` are READ-ONLY → use `shape.resize(w, h)`
156- `parentX`/`parentY` are READ-ONLY → use `penpotUtils.setParentXY(shape, x, y)`
157- Use `insertChild(index, shape)` for z-ordering (not `appendChild`)
158- Flex children array order is REVERSED for `dir="column"` or `dir="row"`
159- After `text.resize()`, reset `growType` to `"auto-width"` or `"auto-height"`
160
161## Positioning New Boards
162
163**Always check existing boards before creating new ones** to avoid overlap:
164
165```javascript
166// Find all existing boards and calculate next position
167const boards = penpotUtils.findShapes(s => s.type === 'board', penpot.root);
168let nextX = 0;
169const gap = 100; // Space between boards
170
171if (boards.length > 0) {
172 // Find rightmost board edge
173 boards.forEach(b => {
174 const rightEdge = b.x + b.width;
175 if (rightEdge + gap > nextX) {
176 nextX = rightEdge + gap;
177 }
178 });
179}
180
181// Create new board at calculated position
182const newBoard = penpot.createBoard();
183newBoard.x = nextX;
184newBoard.y = 0;
185newBoard.resize(375, 812);
186```
187
188**Board spacing guidelines:**
189
190- Use 100px gap between related screens (same flow)
191- Use 200px+ gap between different sections/flows
192- Align boards vertically (same y) for visual organization
193- Group related screens horizontally in user flow order
194
195## Default Design Tokens
196
197**Use these defaults only when user has no design system. Always prefer user's tokens if available.**
198
199### Spacing Scale (8px base)
200
201| Token | Value | Usage |
202| ----- | ----- | ----- |
203| `spacing-xs` | 4px | Tight inline elements |
204| `spacing-sm` | 8px | Related elements |
205| `spacing-md` | 16px | Default padding |
206| `spacing-lg` | 24px | Section spacing |
207| `spacing-xl` | 32px | Major sections |
208| `spacing-2xl` | 48px | Page-level spacing |
209
210### Typography Scale
211
212| Level | Size | Weight | Usage |
213| ----- | ---- | ------ | ----- |
214| Display | 48-64px | Bold | Hero headlines |
215| H1 | 32-40px | Bold | Page titles |
216| H2 | 24-28px | Semibold | Section headers |
217| H3 | 20-22px | Semibold | Subsections |
218| Body | 16px | Regular | Main content |
219| Small | 14px | Regular | Secondary text |
220| Caption | 12px | Regular | Labels, hints |
221
222### Color Usage
223
224| Purpose | Recommendation |
225| ------- | -------------- |
226| Primary | Main brand color, CTAs |
227| Secondary | Supporting actions |
228| Success | #22C55E range (confirmations) |
229| Warning | #F59E0B range (caution) |
230| Error | #EF4444 range (errors) |
231| Neutral | Gray scale for text/borders |
232
233## Common Layouts
234
235### Mobile Screen (375×812)
236
237```text
238┌─────────────────────────────┐
239│ Status Bar (44px) │
240├─────────────────────────────┤
241│ Header/Nav (56px) │
242├─────────────────────────────┤
243│ │
244│ Content Area │
245│ (Scrollable) │
246│ Padding: 16px horizontal │
247│ │
248├─────────────────────────────┤
249│ Bottom Nav/CTA (84px) │
250└─────────────────────────────┘
251
252```
253
254### Desktop Dashboard (1440×900)
255
256```text
257┌──────┬──────────────────────────────────┐
258│ │ Header (64px) │
259│ Side │──────────────────────────────────│
260│ bar │ Page Title + Actions │
261│ │──────────────────────────────────│
262│ 240 │ Content Grid │
263│ px │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
264│ │ │Card │ │Card │ │Card │ │Card │ │
265│ │ └─────┘ └─────┘ └─────┘ └─────┘ │
266│ │ │
267└──────┴──────────────────────────────────┘
268
269```
270
271## Component Checklist
272
273### Buttons
274
275- [ ] Clear, action-oriented label (2-3 words)
276- [ ] Minimum touch target: 44×44px
277- [ ] Visual states: default, hover, active, disabled, loading
278- [ ] Sufficient contrast (3:1 against background)
279- [ ] Consistent border radius across app
280
281### Forms
282
283- [ ] Labels above inputs (not just placeholders)
284- [ ] Required field indicators
285- [ ] Error messages adjacent to fields
286- [ ] Logical tab order
287- [ ] Input types match content (email, tel, etc.)
288
289### Navigation
290
291- [ ] Current location clearly indicated
292- [ ] Consistent position across screens
293- [ ] Maximum 7±2 top-level items
294- [ ] Touch-friendly on mobile (48px targets)
295
296## Accessibility Quick Checks
297
2981. **Color contrast**: Text 4.5:1, Large text 3:1
2992. **Touch targets**: Minimum 44×44px
3003. **Focus states**: Visible keyboard focus indicators
3014. **Alt text**: Meaningful descriptions for images
3025. **Hierarchy**: Proper heading levels (H1→H2→H3)
3036. **Color independence**: Never rely solely on color
304
305## Design Review Checklist
306
307Before finalizing any design:
308
309- [ ] Visual hierarchy is clear
310- [ ] Consistent spacing and alignment
311- [ ] Typography is readable (16px+ body text)
312- [ ] Color contrast meets WCAG AA
313- [ ] Interactive elements are obvious
314- [ ] Mobile-friendly touch targets
315- [ ] Loading/empty/error states considered
316- [ ] Consistent with design system
317
318## Validating Designs
319
320Use these validation approaches with `mcp__penpot__execute_code`:
321
322| Check | Method |
323| ----- | ------ |
324| Elements outside bounds | `penpotUtils.analyzeDescendants()` with `isContainedIn()` |
325| Text too small (<12px) | `penpotUtils.findShapes()` filtering by `fontSize` |
326| Missing contrast | Call `mcp__penpot__export_shape` and visually inspect |
327| Hierarchy structure | `penpotUtils.shapeStructure()` to review nesting |
328
329### Export CSS
330
331Use `penpot.generateStyle(selection, { type: 'css', includeChildren: true })` via `mcp__penpot__execute_code` to extract CSS from designs.
332
333## Tips for Great Designs
334
3351. **Start with content**: Real content reveals layout needs
3362. **Design mobile-first**: Constraints breed creativity
3373. **Use a grid**: 8px base grid keeps things aligned
3384. **Limit colors**: 1 primary + 1 secondary + neutrals
3395. **Limit fonts**: 1-2 typefaces maximum
3406. **Embrace whitespace**: Breathing room improves comprehension
3417. **Be consistent**: Same action = same appearance everywhere
3428. **Provide feedback**: Every action needs a response