Install
openclaw skills install pencil-design-skillDesign UIs in Pencil (.pen files) and generate production-ready code from them. Triggers on any task involving .pen files, UI prototyping, design system authoring, design-to-code conversion, or Pencil MCP tool usage.
openclaw skills install pencil-design-skillDesign production-quality UIs in Pencil and generate clean code. Two modes:
.pen JSON via write_to_file / replace_in_file. Always read references/pen-format.md before writing any .pen file.pencil_batch_design, pencil_batch_get, etc. See MCP tools below..pen files (UI screens, components, design systems)@theme blocks)pen-format.md first before writing any .pen file (Mode A) — contains all node types, variables, layout rules, default templates.ask_followup_question using the menu in styles/style-picker.md. Never silently default to Shadcn Dark."$--background", not "#09090b". If a variable doesn't exist, create it.references/layout-integrity.md + references/overflow-prevention.md. Summary:
"layout": "vertical" or "horizontal" (NOT "none") whenever it holds flowing content. Only use "none" for intentional absolute-positioned decoration (cover / hero slides), and in that case every child MUST stay within the artboard rect."width": "fill_container" + "textGrowth": "fixed-width"."width": "fill_container" and/or "height": "fit_content". Never fix a width larger than the parent's inner width (parent width − horizontal padding).fill_container) + footer MUST equal artboard height. Body area content must never exceed its computed height.gap + width: "fill_container" on each card. Never hand-pick fixed pixel widths that don't divide evenly."fit_content" (padding [v,h]) + "justifyContent": "center" + "alignItems": "center". Never fix a width smaller than the label.x/y for content blocks inside an auto-layout parent..pen files uses 简体中文 unless user explicitly requests otherwise. Technical terms / brand names may stay English.x and y.
W+100, 2(W+100), … Example for 1440×900: x = 0, 1540, 3080, 4620.H+100, 2(H+100), … Example for 1440×900: y = 0, 1000, 2000, 3000. For PPT (1280×720): y = 0, 820, 1640, 2460.Your request has N artboards. Arrange them: 您的请求包含 N 个画板,排列方向:
- Horizontal (default) / 横向排列(默认)
- Vertical / 竖向排列
"iconFontFamily": "lucide". No other families.pencil_batch_get). Copy & resize, do not regenerate. See mcp/image-reuse.md.mcp/screenshot-qa.md..pen task done, run the Layout Integrity Checklist. In Mode B: pencil_snapshot_layout with problemsOnly: true for every artboard must return empty. In Mode A: manually verify each artboard against the checklist.frontend-design skill if available — load it for aesthetic direction.A single .pen file must NEVER contain more than 4 artboards (causes performance issues).
When ≥ 4 artboards are requested, ask the user (in both English and Chinese):
Your request includes N artboards. Please choose a splitting strategy: 您的请求包含 N 个画板。请选择拆分方式:
- One artboard per file / 每个画板一个文件
- Max 3 artboards per file / 每个文件最多 3 个画板
- Max 4 artboards per file / 每个文件最多 4 个画板
- No split (not recommended) / 不拆分(不推荐)
Naming: feature-01.pen, feature-02.pen, … or by logical groups (feature-onboarding.pen).
{
"version": "2.8",
"children": [
{
"type": "frame", "id": "scrn1", "name": "页面",
"theme": { "Mode": "Dark" },
"clip": true, "width": 1440, "height": 900,
"fill": "$--background", "layout": "vertical",
"children": [ ... ]
}
],
"themes": { "Mode": ["Light", "Dark"] },
"variables": { ...copy from pen-format.md "Shadcn Dark Zinc Variables"... }
}
{ "type": "frame", "id": "scrn1", "x": 0, "y": 0, "width": 1440, "height": 900, ... },
{ "type": "frame", "id": "scrn2", "x": 1540, "y": 0, "width": 1440, "height": 900, ... },
{ "type": "frame", "id": "scrn3", "x": 3080, "y": 0, "width": 1440, "height": 900, ... }
{ "type": "frame", "id": "scrn1", "x": 0, "y": 0, "width": 1440, "height": 900, ... },
{ "type": "frame", "id": "scrn2", "x": 0, "y": 1000, "width": 1440, "height": 900, ... },
{ "type": "frame", "id": "scrn3", "x": 0, "y": 2000, "width": 1440, "height": 900, ... }
Common screen sizes: Desktop 1440×900 / 1920×1080 · Tablet 768×1024 · Mobile 375×812 / 393×852.
Named style specs (Vercel / Linear / Stripe / Notion / Raycast / Supabase / Airtable / Apple) are distilled from https://getdesign.md/.
| Trigger | Style file | Notes |
|---|---|---|
| User chose a named style | styles/style-<name>.md | Read only the matching file (vercel / linear / stripe / notion / raycast / supabase / airtable / apple) |
| User skipped / chose "default" | Shadcn Dark Zinc | Variables block lives in pen-format.md. Dark surfaces #09090b / #18181b, light text #fafafa, subtle borders #27272a. |
| PPT / slide deck | ppt/presets-ppt.md | 1280×720, blue gradient header, white body |
1. Confirm style (Rule 2) -> ask user OR read styles/style-<name>.md
2. Read pen-format.md -> mandatory for first .pen task in session
3. Read layout-integrity.md -> mandatory for EVERY .pen task (Rule 5, 11)
4. Plan layout & artboard count -> apply file split policy if ≥ 4
If ≥ 2 artboards, ask arrangement direction (Rule 7) — default HORIZONTAL
5. Write .pen with variables block and auto-layout (NEVER layout:"none" for content)
6. read_lints to validate JSON
7. Manual Layout Integrity Checklist pass (Rule 11) — fix before declaring done
1. Confirm style + load frontend-design skill if available
2. pencil_get_editor_state -> get .pen schema, current state
3. pencil_batch_get reusable=true -> discover existing components (REUSE > recreate)
4. pencil_get_variables -> read tokens; pencil_set_variables to create new
5. pencil_find_empty_space -> place new artboards
6. pencil_batch_design -> build ONE section at a time
7. pencil_get_screenshot + pencil_snapshot_layout(problemsOnly:true) -> verify each section
8. Fix issues -> re-screenshot -> re-check (verify loop)
9. Final full-file layout audit (Rule 11) -> problemsOnly MUST be empty before declaring done
See mcp/mcp-tools.md for the full tool table and Mode B call order.
Always do: TypeScript · React 19 (ref as prop, no forwardRef) · semantic Tailwind classes (bg-primary, never bg-[#3b82f6]) · @theme { --color-* / --radius-* } blocks · Lucide icons · CVA + cn() for variants · OKLCH in tokens.
Never do: arbitrary values (bg-[#fff], rounded-[6px], p-[24px]) · tailwind.config.ts (v4 uses CSS) · forwardRef · hardcoded artboard widths in components (use w-full max-w-7xl).
Detailed mapping: references/codegen-workflow.md + references/codegen-mapping.md.
| File | When |
|---|---|
pen-format.md | Before writing any .pen file |
layout-integrity.md | Before writing any .pen file — hard rules preventing overflow, misalignment, crooked layouts |
Source for named style specs: https://getdesign.md/
| Style | File |
|---|---|
| Style picker / menu | style-picker.md |
| Vercel | style-vercel.md |
| Linear | style-linear.md |
| Stripe | style-stripe.md |
| Notion | style-notion.md |
| Raycast | style-raycast.md |
| Supabase | style-supabase.md |
| Airtable | style-airtable.md |
| Apple | style-apple.md |
| PPT preset | presets-ppt.md |
| File | Topic |
|---|---|
layout-integrity.md | MUST-READ. Hard rules for all UI / PPT — sizing, auto-layout, no-overflow, no-overlap, no-crooked-alignment, artboard budget math |
overflow-prevention.md | Text fill_container rules, mobile constraints, fix patterns |
design-tokens.md | Variable system, theming, Tailwind v4 mapping |
component-reuse.md | ref instances, descendants overrides |
image-reuse.md | Search-before-generate, copy vs regenerate |
screenshot-qa.md | Section-by-section verification (Mode B) |
responsive.md | Artboard sizes → Tailwind breakpoints |
codegen-workflow.md | Full design-to-code workflow |
codegen-mapping.md | Tailwind / shadcn quick mapping tables |
Output rule: user-facing design files must always be saved as
<name>.pen(never.pen.json— that suffix is reserved for skill-internal storage).
| Mistake | Fix |
|---|---|
Hardcoded #3b82f6 in .pen | Use "$--primary" |
Omitting layout on frame | Set "layout": "vertical" or "horizontal" (default is horizontal) |
Using "layout": "none" on a content artboard | Switch to "vertical"; reserve "none" for intentional absolute decoration (cover backgrounds only) |
| Fixed-width text in auto-layout | Use "width": "fill_container" + "textGrowth": "fixed-width" |
| Card/content wider than parent inner width | Use "width": "fill_container" on every row child; size cards via gap on parent |
| Body height overflowing artboard (header + body > artboard) | Use height: "fill_container" on the body frame, fixed heights only for header/footer |
| Button with hardcoded width smaller than label | Use "fit_content" + padding: [v, h] + justifyContent: "center" |
Hand-computed x/y inside auto-layout parent | Let auto-layout position children; use gap/padding instead |
| Text touching artboard edges | Apply horizontal padding (desktop 40–64px, tablet 24–32px, mobile 16–20px) |
| Long descriptive IDs | Use 5-char codes: "btn01", "crd1a" |
bg-[#fff] in code | Use bg-background, text-foreground |
tailwind.config.ts | Use CSS @theme (Tailwind v4) |
| English UI text | Default to Simplified Chinese |
| Silently using Shadcn Dark | Always ask user for style first (Rule 2) |
| Cramming 5+ artboards in one file | Apply file split policy (Rule 3) |
| Skipping final layout audit | Run Layout Integrity Checklist before declaring done (Rule 11) |