Communitygithub.com

stevembarclay/pencilplaybook

PencilPlaybook est le carnet de design UI / skill de goût pour Pencil.dev + Claude Code — un manuel de design qui donne à Claude une réelle psychologie perceptuelle et des garde-fous de niveau senior pour qu'il cesse de produire du design générique et médiocre.

Qu'est-ce que pencilplaybook ?

PencilPlaybook est une compétence UI spécialisée conçue pour fonctionner avec Pencil.dev et Claude Code. Elle agit comme un carnet de design senior qui fournit à l'IA des conseils basés sur la psychologie perceptuelle réelle et des garde-fous de conception. L'objectif principal est d'empêcher l'IA de produire des designs génériques et médiocres en lui offrant des règles de résolution, des échafaudages de mise en page standardisés et des flux de travail de design éprouvés. La compétence prend en charge Pencil.dev et est destinée aux développeurs et concepteurs qui utilisent Claude Code pour le prototypage UI. Elle fonctionne en injectant des tokens de marque, en chargeant des directives de design, et en utilisant quatre-vingt-dix scripts d'échafaudage couvrant des archétypes de mise en page courants (dashboard, liste, détail, page marketing, modal, assistant, mobile, formulaire, état vide). Elle inclut également des flux de travail d'archéologie de canvas, des directives de responsivité, et des points de décision pour la conception mobile-first.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add stevembarclay/pencilplaybook

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Pencil Pro

Règle de Résolution Primaire

Cette compétence doit être configurée avant la première utilisation.

Si l'utilisateur dit « exécuter l'assistant de configuration PencilPlaybook » ou demande à configurer PencilPlaybook : → Lisez .claude/skills/pencilplaybook/setup.md et suivez les instructions qui s'y trouvent exactement.

Si l'utilisateur dit « créer mon premier écran avec PencilPlaybook » ou demande à commencer le design : → Lisez .claude/skills/pencilplaybook/onboarding.md et suivez les instructions qui s'y trouvent exactement.

Résolution configurée : (exécutez la configuration pour définir cela)

Si une racine d'écran dans un fichier .pen existant ne correspond pas à votre résolution configurée, notez-la avant de modifier. Ne construisez pas sur un canvas de taille incorrecte sans signaler la déviation.

Exception courante — pages marketing : Design à 1440px quelle que soit votre résolution d'application. Les pages marketing sont consommées à des largeurs de navigateur variables — design à 1440px, vérifiez à 390px.


Démarrage de Session (Chaque Session Pencil)

1. get_editor_state()                           — vérifier le document actif et la sélection
2. open_document("path/to/your-file.pen")       — ouvrir le fichier cible
3. get_guidelines(topic="web-app")              — charger les directives de design
4. set_variables(<token map ci-dessous>)         — injecter les tokens de marque
5. get_variables()                              — confirmer que les tokens sont stockés
6. snapshot_layout()                            — vérifier les dimensions du canvas

Votre token map — exécutez set_variables avec cet objet au début de chaque session. Les variables peuvent ne pas persister entre les sessions 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"
}

Après set_variables, appelez get_variables() pour confirmer que tous les tokens sont stockés.


Scripts d'Échafaudage

Neuf scripts d'échafaudage couvrant les archétypes de mise en page les plus courants. Exécutez l'assistant de configuration pour remplir les valeurs de dimensions et de couleurs ci-dessous avant utilisation.


Échafaudage A — Tableau de Bord d'Application

Métriques, KPI, flux d'activité, surveillance

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

Après échafaudage : snapshot_layout() — vérifiez que pageArea.width et contentInner.width sont corrects.


Échafaudage B — Liste / File d'Attente d'Application

Tableaux, bibliothèques d'actifs, files d'attente, gestion des utilisateurs

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

Échafaudage C — Détail / Révision d'Application

Vues détaillées à deux panneaux, flux de révision, mises en page côte à côte

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

Remarque : La division gauche/droite par défaut est d'environ 40/60. Ajustez selon la fonctionnalité — divisions courantes : 40/60, 38/62, 50/50.


Échafaudage D — Page Marketing

Pages d'atterrissage, pages produit — toujours 1440px de large, quelle que soit le canvas de l'application

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

Les pages marketing sont mobile-first. Design à 1440px et vérifiez la mise en page à 390px de large avant la remise.


Échafaudage E — Modal / Boîte de Dialogue

Confirmations, actions destructrices, formulaires de modification rapide, panneaux latéraux

Exécutez d'abord l'échafaudage A, B ou C. Ajoutez ensuite cette modale superposée sur pageArea — ne l'insérez pas dans la racine.

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

Après échafaudage : snapshot_layout() — confirmez que la modale est visible et centrée. Ajustez la largeur de la modale selon le cas d'utilisation : 380px (confirmation compacte), 480px (formulaire standard), 600px (formulaire large), 720px (détail/aperçu).


Échafaudage F — Assistant / Étapes

Formulaires multi-étapes, flux d'intégration, séquences de configuration, paiement

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

Remarque : ContentInner fait 640px de large par défaut — formulaire à une colonne ciblé. Bouton retour à gauche, Suivant/Valider à droite dans ActionFooter (justifyContent:"space-between").


Échafaudage G — Écran Mobile

390×844px (standard iPhone 14). Utilisez ceci pour tous les écrans mobiles — codé en dur, aucune valeur de configuration requise.

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

Remarque : Supprimez statusBar et définissez navBar.y=0 si l'interface système n'est pas affichée. Supprimez bottomNav pour les applications sans navigation par onglets. Les cibles tactiles dans cet échafaudage doivent être ≥44×44px.


Échafaudage H — Formulaire / Saisie de Données

Pages de paramètres, édition de profil, saisie de données intensive — formulaire centré à une colonne

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

Remarque : La largeur de FormInner par défaut est de 600px. Utilisez 480px pour les flux simples, 800px pour les mises en page larges à deux colonnes. Ajoutez plus de nœuds FormSection dans formInner pour regrouper les champs connexes.


Échafaudage I — État Vide / Étape d'Intégration

Vues sans données, invites de première utilisation, découverte de fonctionnalités, écrans vierges

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

Remarque : Remplacez IllustrationArea par G("illustrationArea", "ai", "your prompt") pour générer une illustration. Gardez le texte de l'état vide court : un titre (16–18px), une ligne de support (14px atténué), un bouton d'action principal.


Flux de Travail Principaux

Flux de Travail 1 : Archéologie du Canvas

Utilisez quand : « qu'est-ce qu'il y a dans ce fichier .pen ? » → vérifiez les dimensions et la structure d'un fichier .pen existant.

1. get_editor_state() → notez le document actif
2. snapshot_layout() → prenez un instantané du canvas pour inspection
3. Obtenez les dimensions du canvas : hauteur, largeur, éléments enfants
4. Notez les écarts de résolution

Flux de Travail 2 : Injection de Marque

1. set_variables(<token map>) → injectez les tokens de marque
2. get_variables() → confirmez que les tokens sont stockés
3. Vérifiez que les tokens correspondent au thème prévu

Flux de Travail 3 : Responsivité

Règle générale : les points de rupture sont à 640px, 1024px, 1440px. Utilisez les échafaudages G (mobile) pour mobile, les échafaudages standard pour desktop.

Pour les vérifications de responsivité :

1. Après le design à 1440px, dupliquez le canvas et redimensionnez à 390px
2. Vérifiez : les éléments ne doivent pas se chevaucher, le texte doit rester lisible, les cibles tactiles doivent être ≥44×44px
3. Ajustez les mises en page flexibles pour s'adapter à la largeur réduite

Conseils de Conception

  1. Utilisez les échafaudages systématiquement — ils encapsulent des années de décisions de conception. Ne les écartez pas sans justifier pourquoi.
  2. Préférez les tokens à la surcharge visuelle — utilisez C("votre.text", tokens) plutôt que des valeurs codées en dur.
  3. Conception mobile-first — si le design doit être responsive, commencez par l'échafaudage G, puis développez.
  4. Psychologie perceptuelle — regroupez les éléments connexes visuellement (Loi de Proximité), utilisez des en-têtes cohérents (Loi de Similarité), laissez de l'espace autour des éléments importants (Loi de l'Espace).
  5. Accessibilité — le contraste du texte doit être ≥4,5:1, les cibles tactiles ≥44×44px, n'utilisez pas la couleur seule pour véhiculer l'information.
  6. Consistance — utilisez les mêmes espacements, polices et couleurs dans tout le design. Les tokens de l'assistant de configuration aident à cela.

Journal des Modifications

  • v1.0.0 — Version initiale avec 9 échafaudages, assistant de configuration, flux de travail d'archéologie du canvas.

Skills associés