- name
- pencilplaybook
- description
- PencilPlaybook is the UI Skills / Taste-Skill for Pencil.dev + Claude Code — a design playbook that gives Claude real perceptual psychology and senior-level guardrails so it stops producing averaged-out AI slop.
- version
- 1.1.0
# Pencil Pro
## Primary Resolution Rule
**This skill must be configured before first use.**
**If the user says "run the PencilPlaybook setup wizard" or asks to set up or configure PencilPlaybook:**
→ Read `.claude/skills/pencilplaybook/setup.md` and follow the instructions there exactly.
**If the user says "build my first screen with PencilPlaybook" or asks to start designing:**
→ Read `.claude/skills/pencilplaybook/onboarding.md` and follow the instructions there exactly.
> Configured resolution: *(run setup to set this)*
If a screen root in an existing `.pen` file doesn't match your configured resolution, note it before editing. Do not build on top of a wrongly-sized canvas without flagging the deviation.
**Common exception — marketing pages:** Design at 1440px regardless of your app resolution. Marketing pages are consumed at variable browser widths — design at 1440px, verify at 390px.
---
## Session Startup (Every Pencil Session)
```
1. get_editor_state() — check active document and selection
2. open_document("path/to/your-file.pen") — open target file
3. get_guidelines(topic="web-app") — load design guidelines
4. set_variables(<token map below>) — inject brand tokens
5. get_variables() — confirm tokens stored
6. snapshot_layout() — verify canvas dimensions
```
**Your token map** — run `set_variables` with this object at the start of every session. Variables may not persist between Claude Code sessions.
```json
{
"color-primary": "YOUR_HEX",
"color-primary-dark": "YOUR_HEX",
"color-accent": "YOUR_HEX",
"color-background": "YOUR_HEX",
"color-surface": "YOUR_HEX",
"color-border": "YOUR_HEX",
"color-text": "YOUR_HEX",
"color-text-muted": "YOUR_HEX",
"color-success": "YOUR_HEX",
"color-warning": "YOUR_HEX",
"color-error": "YOUR_HEX",
"font-sans": "YOUR_FONT",
"font-mono": "YOUR_FONT",
"font-serif": "YOUR_FONT",
"spacing-card": "24",
"spacing-gap-sm": "8",
"spacing-gap-md": "16",
"spacing-gap-lg": "24",
"spacing-gap-xl": "32",
"content-max-width": "YOUR_VALUE",
"sidebar-width": "YOUR_VALUE"
}
```
After `set_variables`, call `get_variables()` to confirm all tokens are stored.
---
## Scaffold Scripts
Nine scaffold scripts covering the most common layout archetypes. Run the setup wizard to fill in the dimension and color values below before using.
---
### Scaffold A — App Dashboard
*Metrics, KPIs, activity feed, monitoring*
```
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG", display:"flex", flexDirection:"column"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:32})
statsBar=I("pageArea", {name:"StatsBar", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:80, bg:"STATS_BG", display:"flex", alignItems:"center", gap:24, px:32})
contentWrap=I("pageArea", {name:"ContentWrap", y:144, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_A, display:"flex", justifyContent:"center", p:32})
contentInner=I("contentWrap", {name:"ContentInner", width:SCAFFOLD_CONTENT_MAX, display:"flex", flexDirection:"column", gap:24})
```
After scaffold: `snapshot_layout()` — verify pageArea.width and contentInner.width are correct.
---
### Scaffold B — App List / Queue
*Tables, asset libraries, queues, user management*
```
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:32})
commandStrip=I("pageArea", {name:"CommandStrip", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:52, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", gap:16, px:32})
tableWrap=I("pageArea", {name:"TableWrap", y:116, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_B, display:"flex", justifyContent:"center", px:32, pt:24})
tableInner=I("tableWrap", {name:"TableInner", width:SCAFFOLD_CONTENT_MAX, display:"flex", flexDirection:"column", gap:0})
tableHeader=I("tableInner", {name:"TableHeader", width:SCAFFOLD_CONTENT_MAX, height:40, bg:"TABLE_HEADER_BG", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center"})
```
---
### Scaffold C — App Detail / Review
*Two-panel detail views, review flows, side-by-side layouts*
```
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR"})
actionBar=I("pageArea", {name:"ActionBar", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:56, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR"})
contentWrap=I("pageArea", {name:"ContentWrap", y:120, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_C, display:"flex", justifyContent:"center"})
contentInner=I("contentWrap", {name:"ContentInner", width:SCAFFOLD_CONTENT_MAX, height:SCAFFOLD_CONTENT_HEIGHT_C, display:"flex", gap:0})
leftPanel=I("contentInner", {name:"LeftPanel", width:SCAFFOLD_LEFT_PANEL, height:SCAFFOLD_CONTENT_HEIGHT_C, bg:"SURFACE_COLOR", borderRight:"1px solid BORDER_COLOR"})
rightPanel=I("contentInner", {name:"RightPanel", width:SCAFFOLD_RIGHT_PANEL, height:SCAFFOLD_CONTENT_HEIGHT_C, bg:"PAGE_BG", p:24, display:"flex", flexDirection:"column", gap:20})
```
Note: left/right split defaults to ~40/60. Adjust per feature — common splits: 40/60, 38/62, 50/50.
---
### Scaffold D — Marketing Page
*Landing pages, product pages — always 1440px wide regardless of app canvas*
```
navbar=I("root", {name:"Navbar", width:1440, height:72, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:80})
heroSection=I("root", {name:"HeroSection", y:72, width:1440, height:600, bg:"HERO_BG", display:"flex", flexDirection:"column", alignItems:"center", justifyContent:"center"})
heroContent=I("heroSection", {name:"HeroContent", width:SCAFFOLD_MARKETING_CONTENT_MAX, display:"flex", flexDirection:"column", alignItems:"center", gap:24})
section1=I("root", {name:"Section1", y:672, width:1440, height:480, bg:"SURFACE_COLOR", display:"flex", flexDirection:"column", alignItems:"center", py:80})
section1Content=I("section1", {name:"Section1Content", width:SCAFFOLD_MARKETING_CONTENT_MAX})
```
Marketing pages are mobile-first. Design at 1440px and verify the layout at 390px width before handoff.
---
### Scaffold E — Modal / Dialog
*Confirmations, destructive actions, quick-edit forms, side peek panels*
Run Scaffold A, B, or C first. Then add this modal overlaid on the pageArea — do not insert into the root.
```
backdrop=I("pageArea", {name:"ModalBackdrop", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"rgba(0,0,0,0.48)", display:"flex", alignItems:"center", justifyContent:"center"})
modal=I("backdrop", {name:"Modal", width:480, bg:"SURFACE_COLOR", borderRadius:8, border:"1px solid BORDER_COLOR", display:"flex", flexDirection:"column", overflow:"hidden"})
modalHeader=I("modal", {name:"ModalHeader", height:56, px:24, display:"flex", alignItems:"center", justifyContent:"space-between", borderBottom:"1px solid BORDER_COLOR"})
modalBody=I("modal", {name:"ModalBody", px:24, py:20, display:"flex", flexDirection:"column", gap:16})
modalFooter=I("modal", {name:"ModalFooter", height:60, px:24, display:"flex", alignItems:"center", justifyContent:"flex-end", gap:12, borderTop:"1px solid BORDER_COLOR"})
```
After scaffold: `snapshot_layout()` — confirm modal is visible and centered. Adjust modal width per use case: 380px (compact confirmation), 480px (standard form), 600px (wide form), 720px (detail/preview).
---
### Scaffold F — Wizard / Stepper
*Multi-step forms, onboarding flows, setup sequences, checkout*
```
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:32})
stepperBar=I("pageArea", {name:"StepperBar", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:60, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", justifyContent:"center"})
contentWrap=I("pageArea", {name:"ContentWrap", y:124, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_F, display:"flex", justifyContent:"center", px:32, pt:32})
contentInner=I("contentWrap", {name:"ContentInner", width:640, display:"flex", flexDirection:"column", gap:24})
actionFooter=I("pageArea", {name:"ActionFooter", y:SCAFFOLD_WIZARD_FOOTER_Y, width:SCAFFOLD_PAGE_AREA_WIDTH, height:72, bg:"SURFACE_COLOR", borderTop:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", justifyContent:"space-between", px:32})
```
Note: ContentInner is 640px wide by default — focused single-column form. Back button left, Next/Submit right in ActionFooter (`justifyContent:"space-between"`).
---
### Scaffold G — Mobile Screen
*390×844px (iPhone 14 standard). Use this for all mobile screens — hardcoded, no setup values required.*
```
statusBar=I("root", {name:"StatusBar", width:390, height:44, bg:"PAGE_BG"})
navBar=I("root", {name:"NavBar", y:44, width:390, height:56, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:16})
scrollContent=I("root", {name:"ScrollContent", y:100, width:390, height:688, bg:"PAGE_BG", display:"flex", flexDirection:"column", overflow:"hidden"})
Auf GitHub ansehen