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: 캔버스 고고학
다음과 같은 경우 사용: "이 ...에 무엇이 있나요?"
(원본 콘텐츠가 잘렸습니다. 전체 내용을 보려면 원본 문서를 확인하세요.)