Communitygithub.com

stevembarclay/pencilplaybook

PencilPlaybook는 Pencil.dev + Claude Code를 위한 UI 스킬/취향 스킬입니다. 실제 지각 심리학과 시니어 수준의 가드레일을 Claude에 제공하여 평균적인 AI 결과물을 생성하지 않도록 하는 디자인 플레이북입니다.

pencilplaybook란 무엇인가요?

PencilPlaybook는 Claude Code와 함께 사용되는 디자인 가드레일 시스템으로, Pencil.dev 캔버스에서 UI를 디자인할 때 Claude가 평범하고 일반적인 결과물을 생성하지 않도록 방지합니다. 이 스킬은 실제 지각 심리학 원칙과 시니어 수준의 디자인 규칙을 Claude에게 주입하여, 심미적으로 뛰어나고 사용성 높은 인터페이스를 일관되게 제작하도록 합니다. 주요 기능은 아홉 가지 스캐폴드 스크립트로, 앱 대시보드, 목록/큐, 상세 보기, 마케팅 페이지, 모달/대화상자, 마법사/스테퍼, 모바일 화면, 양식/데이터 입력, 빈 상태/온보딩 단계 등 가장 일반적인 레이아웃 아키텍처를 즉시 생성할 수 있습니다. 각 스캐폴드는 브랜드 토큰과 해상도를 기반으로 자동 크기 및 색상 설정을 지원합니다. 설정 마법사(setup wizard)를 통해 처음 사용 시 브랜드 색상, 글꼴, 여백, 캔버스 해상도 등을 구성할 수 있으며, 이후 모든 세션 시작 시 자동으로 해당 변수가 주입됩니다. 마케팅 페이지는 1440px, 모바일 화면은 390×844px 등 디바이스별 최적 해상도가 설정되어 있으며, 반응형 검증 워크플로우도 포함되어 있습니다. 이 스킬은 Claude Code, Cursor, 그리고 모든 AI 에이전트와 호환되며, Pencil.dev를 사용하는 디자이너와 개발자 모두에게 적합합니다. 평범한 UI를 지양하고 인간 수준의 디자인 감각을 유지하려는 팀에게 특히 유용합니다.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add stevembarclay/pencilplaybook

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Pencil Pro

기본 해결 규칙

이 스킬은 처음 사용하기 전에 반드시 설정해야 합니다.

사용자가 "PencilPlaybook 설정 마법사 실행"이라고 말하거나 PencilPlaybook을 설정하라고 요청하는 경우: → .claude/skills/pencilplaybook/setup.md 파일을 읽고 그 안의 지침을 정확히 따르세요.

사용자가 "PencilPlaybook으로 첫 화면 만들기"라고 말하거나 디자인을 시작하라고 요청하는 경우: → .claude/skills/pencilplaybook/onboarding.md 파일을 읽고 그 안의 지침을 정확히 따르세요.

설정된 해상도: (설정을 실행하여 이 값을 설정하세요)

기존 .pen 파일의 화면 루트가 설정된 해상도와 일치하지 않으면 편집하기 전에 이를 기록하세요. 잘못된 크기의 캔버스 위에 구축하지 말고, 항상 차이를 표시하세요.

일반적인 예외 — 마케팅 페이지: 앱 해상도와 관계없이 1440px로 디자인하세요. 마케팅 페이지는 다양한 브라우저 너비로 소비됩니다 — 1440px에서 디자인하고, 390px에서 확인하세요.


세션 시작 (모든 Pencil 세션)

1. get_editor_state()                           — 활성 문서 및 선택 항목 확인
2. open_document("path/to/your-file.pen")       — 대상 파일 열기
3. get_guidelines(topic="web-app")              — 디자인 가이드라인 로드
4. set_variables(<아래 토큰 맵>)                 — 브랜드 토큰 주입
5. get_variables()                              — 토큰 저장 확인
6. snapshot_layout()                            — 캔버스 크기 확인

토큰 맵 — 모든 세션 시작 시 아래 객체로 set_variables를 실행하세요. 변수는 Claude Code 세션 간에 유지되지 않을 수 있습니다.

{
  "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"
}

set_variables 후에 get_variables()를 호출하여 모든 토큰이 저장되었는지 확인하세요.


스캐폴드 스크립트

가장 일반적인 레이아웃 아키텍처를 다루는 아홉 가지 스캐폴드 스크립트입니다. 사용하기 전에 설정 마법사를 실행하여 아래의 크기 및 색상 값을 입력하세요.


스캐폴드 A — 앱 대시보드

메트릭, KPI, 활동 피드, 모니터링

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})

스캐폴드 후: snapshot_layout() — pageArea.width 및 contentInner.width가 올바른지 확인하세요.


스캐폴드 B — 앱 목록 / 큐

테이블, 자산 라이브러리, 큐, 사용자 관리

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"})

스캐폴드 C — 앱 상세 / 검토

2패널 상세 보기, 검토 흐름, 나란히 배치 레이아웃

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})

참고: 좌/우 분할은 기본적으로 약 40/60입니다. 기능에 따라 조정하세요 — 일반적인 분할: 40/60, 38/62, 50/50.


스캐폴드 D — 마케팅 페이지

랜딩 페이지, 제품 페이지 — 앱 캔버스와 관계없이 항상 1440px 너비

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})

마케팅 페이지는 모바일 우선입니다. 1440px에서 디자인하고 전달 전에 390px 너비에서 레이아웃을 확인하세요.


스캐폴드 E — 모달 / 대화상자

확인, 파괴적 작업, 빠른 편집 폼, 측면 미리보기 패널

먼저 스캐폴드 A, B 또는 C를 실행하세요. 그런 다음 이 모달을 pageArea 위에 오버레이로 추가하세요 — 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"})

스캐폴드 후: snapshot_layout() — 모달이 표시되고 중앙에 위치하는지 확인하세요. 사용 사례에 따라 모달 너비 조정: 380px(간결한 확인), 480px(표준 폼), 600px(넓은 폼), 720px(상세/미리보기).


스캐폴드 F — 마법사 / 스테퍼

다단계 폼, 온보딩 흐름, 설정 시퀀스, 체크아웃

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})

참고: ContentInner의 기본 너비는 640px입니다 — 집중된 단일 열 폼입니다. 뒤로 가기 버튼은 왼쪽, 다음/제출은 ActionFooter 오른쪽에 있습니다(justifyContent:"space-between").


스캐폴드 G — 모바일 화면

390×844px (iPhone 14 표준). 모든 모바일 화면에 이것을 사용하세요 — 하드코딩, 설정 값 불필요.

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"})
contentPad=I("scrollContent", {name:"ContentPad", width:390, display:"flex", flexDirection:"column", gap:16, px:16, pt:16})
bottomNav=I("root", {name:"BottomNav", y:788, width:390, height:56, bg:"SURFACE_COLOR", borderTop:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", justifyContent:"space-around"})

참고: 시스템 크롬을 표시하지 않을 경우 statusBar를 제거하고 navBar.y=0으로 설정하세요. 탭 내비게이션이 없는 앱의 경우 bottomNav를 제거하세요. 이 스캐폴드 내의 터치 대상은 반드시 ≥44×44px이어야 합니다.


스캐폴드 H — 폼 / 데이터 입력

설정 페이지, 프로필 편집, 대규모 데이터 입력 — 단일 열, 중앙 정렬 폼

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", justifyContent:"space-between", px:32})
formWrap=I("pageArea", {name:"FormWrap", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_H, display:"flex", justifyContent:"center", px:32, pt:32})
formInner=I("formWrap", {name:"FormInner", width:600, display:"flex", flexDirection:"column", gap:28})
formSection=I("formInner", {name:"FormSection1", display:"flex", flexDirection:"column", gap:16})
formActions=I("formInner", {name:"FormActions", display:"flex", gap:12, justifyContent:"flex-end"})

참고: FormInner의 기본 너비는 600px입니다. 간단한 흐름은 480px, 넓은 2열 레이아웃은 800px을 사용하세요. 관련 필드를 그룹화하려면 formInner 내부에 FormSection 노드를 더 추가하세요.


스캐폴드 I — 빈 상태 / 온보딩 단계

데이터가 없는 보기, 첫 사용 프롬프트, 기능 발견, 빈 슬레이트 화면

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"})
emptyCenter=I("pageArea", {name:"EmptyCenter", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_H, display:"flex", alignItems:"center", justifyContent:"center"})
emptyContent=I("emptyCenter", {name:"EmptyContent", width:400, display:"flex", flexDirection:"column", alignItems:"center", gap:20})
illustrationArea=I("emptyContent", {name:"IllustrationArea", width:200, height:160, borderRadius:12, bg:"SURFACE_COLOR", border:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", justifyContent:"center"})
textStack=I("emptyContent", {name:"TextStack", width:400, display:"flex", flexDirection:"column", alignItems:"center", gap:8})
emptyActions=I("emptyContent", {name:"EmptyActions", display:"flex", gap:12})

참고: IllustrationArea를 G("illustrationArea", "ai", "your prompt")로 대체하여 일러스트레이션을 생성하세요. 빈 상태 텍스트는 짧게 유지하세요: 하나의 헤드라인(16–18px), 하나의 보조 텍스트(14px, 흐릿하게), 하나의 기본 CTA.


핵심 워크플로우

워크플로우 1: 캔버스 고고학

다음과 같은 경우 사용: "이 ...에 무엇이 있나요?"

(원본 콘텐츠가 잘렸습니다. 전체 내용을 보려면 원본 문서를 확인하세요.)

관련 스킬