Document a Penpot design for handoff by building a clean annotation layer BESIDE the design (never on top of it): a left context card (the 'How might we' goal, business rules, links, status, feedback wanted/not), numbered pin markers on the UI, matching observation/recommendation note cards on the right, and optional tooltips — all wrapped in a single hideable group so the clean design can be revealed. Reuses an annotation component kit + tokens if present; proposes and creates a minimal one if missing. NOT for auditing (use penpot-audit-*) or renaming layers (use penpot-rename-layers). Triggers: 'document this design', 'annotate this screen', 'prepare this for handoff', 'add design annotations', 'explain this flow for devs', 'add observation notes', 'create a critique card', 'spec this screen for handoff'.
Document a Penpot design for handoff by building a clean annotation layer BESIDE the design (never on top of it): a left context card (the 'How might we' goal, business rules, links, status, feedback wanted/not), numbered pin markers on the UI, matching observation/recommendation note cards on the right, and optional tooltips — all wrapped in a single hideable group so the clean design can be revealed. Reuses an annotation component kit + tokens if present; proposes and creates a minimal one if missing. NOT for auditing (use penpot-audit-*) or renaming layers (use penpot-rename-layers). Triggers: 'document this design', 'annotate this screen', 'prepare this for handoff', 'add design annotations', 'explain this flow for devs', 'add observation notes', 'create a critique card', 'spec this screen for handoff'.
penpot-document-handoff turns a finished (or in-progress) design into a self-explaining handoff:
a context card to its left, numbered pins on the UI regions, matching note cards to its
right, and optional tooltips for transient states — every annotation living in one hideable
group so reviewers can toggle back to the clean design. Every mutation goes through execute_code;
validate visually with export_shape; read structure with penpotUtils.shapeStructure (full tool
surface: shared/penpot-mcp-tool-reference.md). It first discovers the target
design + any existing annotation component kit and tokens, then builds the annotation layer
incrementally — one annotation per call — strictly as a sibling layer, never editing the
design itself.
2. The One Rule That Matters Most
Annotate beside, never on top — and one annotation per call. The design being documented is
read-only: you add a separate, hideable annotation layer next to it and you never move, restyle, or
restructure a single shape of the original. Build the context card, then add pins+notes one at a time,
checkpointing as you go. Generating the whole annotation set in one execute_code call is a failure
mode.
3. Penpot MCP Tool Reference
Full surface: shared/penpot-mcp-tool-reference.md. Key calls this skill leans on:
penpotUtils.shapeStructure / findShape / findShapes (locate the design + kit components);
penpot.library.local.components + comp.instance() (reuse the annotation kit); penpot.createBoard()
/ addFlexLayout() (build the kit if missing); penpot.group() (the hideable wrapper — verify with
penpot_api_info); shape.applyToken (bind accent/surface/type); export_shape('selection'|<id>) at
every checkpoint.
4. Plugin API Essentials
Gotcha numbers refer to shared/plugin-api-gotchas.md.
The design is read-only input. Read it with shapeStructure; resolve pin anchor points from
child bounds (absolute x/y/width/height). Never call resize/reparent// on it.
detach
remove
Annotation cards are Boards with flex (column-reverse, matching the reference system); compose
with append order + gaps + padding, never absolute x/y inside a card.
Pins and the context card sit at absolute page positions (they are not inside the design's
layout) — set x/y directly, or layoutChild.absolute = true if parented into a layout board
(#14: absolute children use PAGE coordinates, and boards clip at their edges).
#3 text auto-sizing — set growType to auto-width/auto-height after any resize() (which
forces fixed); sleep ~100 ms before reading back textBounds.
#2 async token application — apply in one call, verify resolvedValue in a LATER call.
#11 every new Board is born with an OPAQUE WHITE fill — this skill's critical failure mode.createBoard() ships fills = [{ fillColor: "#FFFFFF", fillOpacity: 1 }]. Left in place, a
structural wrapper's square white corners poke out behind the rounded card it wraps, and any board
keeping the literal white is off-system (never themes). Fill policy: note/context cards and
tooltips are genuine surfaces → bind their bg to color.annotation.surface (never a literal);
inner section boards and wrappers are structural → clear with board.fills = [].
Wrap-to-hide: collect every annotation shape and group() them under one named group; hiding =
group.hidden = true. Verify group() / grouping signature with penpot_api_info before relying on it.
5. Token-Aware Brief Contract
Restate the request before mutating. Act as a senior design-systems / handoff specialist who never
annotates on top of the work and never hardcodes the annotation palette.
Context — product, audience, the feature/flow being documented, target reader (devs? PMs? design
critique?).
Objective — the single design (board/frame or selection) to document and what the handoff must
make unambiguous.
Inputs — the design board id; the handoff brief content (US number, title, the "How might we"
goal, context/business rules, links, designer(s), status, platform, feedback wanted / not wanted);
the list of UI regions to pin with their observation (and optional recommendation) text; any
transient states needing tooltips.
Constraints — do not modify the design; reuse the annotation kit if present (else propose one);
bind accent/surface/type to tokens (propose annotation.* tokens if missing — human approves);
pins numbered contiguously and matched 1:1 to notes; everything inside the hideable group.
Acceptance Criteria — design byte-for-byte untouched; every pin has exactly one matching note and
vice-versa; numbering contiguous from 1; all annotation text bound to annotation type tokens; accent
& surface bound to tokens; the whole layer hides/shows from one group toggle; 3-column reading order
(context | design | notes) holds.
6. Mandatory Workflow
Visual self-review (mandatory): before every ✋ checkpoint that shows visual work,
run the export → look → fix loop from shared/visual-self-review.md — export the unit you
just built, inspect the image yourself against the checklist, fix visible defects (max 2
iterations), and present that same export with any remaining defects named.
Phase 0 — Discovery (read-only).high_level_overview; resolve the target design
(penpot.selection or a named board) and copy its id into storage.dh; read its structure
(scripts/locateDesign pattern, depth 2–3) to enumerate pinnable regions; inventory the annotation kit
tokens (scripts/setupAnnotationKit.js in dryRun). ✋ Checkpoint: confirm the design + whether
a kit exists or must be created.
Phase 1 — Handoff brief. Collect/confirm the context-card content and the pin list (region →
observation → optional recommendation). Use references/02-handoff-brief.md / prompts/handoff-brief.md.
✋ Checkpoint: approve the brief + pin list before any drawing.
Phase 2 — Ensure the annotation kit. If the kit components + annotation.* tokens exist, reuse
them. If not, propose the minimal kit (Critique Card, Chip Note, Pointer S/L, Tooltip) + tokens
(color.annotation.accent, color.annotation.surface, color.annotation.on-accent,
color.annotation.body, font.annotation.title|body|label) per references/04-component-and-tokens.md,
and create it only after approval (scripts/setupAnnotationKit.js). ✋ Checkpoint: approve kit +
token names/values/tier.
Phase 3 — Context card. Build/instance the Critique Card, fill it from the brief, place it to the
left of the design (scripts/buildContextCard.js). ✋ Checkpoint:export_shape the card.
Phase 4 — Pins + notes (one per call). For each region: place a numbered Pointer/L pin anchored to
the region on the design, and a matching Chip Note in the right column with the same number
(scripts/placePinAndNote.js). Optionally add a Tooltip for a transient state
(scripts/addTooltipCallout.js). One annotation per execute_code call.✋ Checkpoint:export_shape after each (or each small batch).
Phase 5 — Wrap & audit. Group every annotation shape under one hideable group named
Hide this to quit notes; run the self-audit (scripts/finalizeHandoff.js): design untouched, pin↔note
parity, contiguous numbering, tokens bound, 3-column order. A non-empty violations fails the gate —
fix before reporting done. Report.
7. Critical Rules
Never modify the design. No geometry, fill, name, or structure change on any original shape. The
skill only adds a sibling annotation layer. The Phase 5 audit fails the run if the design's shape
set or bounds changed.
One annotation per execute_code call. Context card, then each pin+note individually. Never
one-shot the whole layer.
Pin↔note parity & contiguous numbering. Every Pointer pin has exactly one Chip Note with the
same number; numbers run 1..N with no gaps; the on-canvas pin (L) and the note's header pin (S) share
the number.
Reuse the kit; propose tokens, never hardcode. Instance existing annotation components; if the
kit/tokens are missing, propose and create them under review — never paint raw #1A88E0/#E4F3FF.
3-column layout. Context card left, design center (untouched), note cards stacked right; pins
overlay the regions they point to.
Flex inside every card. Cards/sections are flex Boards (column-reverse like the reference), not
absolute-positioned text or plain Groups.
Everything hideable from one group. All annotation shapes live under a single named group so
reviewers toggle the clean design with one click.
Default mode = review. Geometry is created → checkpoint at each phase; kit/token creation is a
never-autofix change requiring approval.
8. Domain Architecture
The annotation layer is three columns around the untouched design:
[ Critique Card ] [ the design (read-only) ] [ Chip Note #1 ]
#US · title ┌─────────┐ number+TITLE
State/Copy/Platform │ ① ② ③ │ ← Pointer/L pins Observation
status pill │ UI… │ on the regions Recommendation?
HMW goal └─────────┘ [ Chip Note #2 ] …
links · designers (+ Tooltip/Top|Bottom for
context transient states)
feedback wanted
feedback NOT wanted
All of it (cards + pins + tooltips) is wrapped in one group: Hide this to quit notes.
Component kit + token taxonomy: references/01-annotation-anatomy.md, references/04-component-and-tokens.md.
9. Modes & Policies
Default review (shared/modes-and-policies.md). Creating geometry, components, or tokens always
requires a checkpoint. Safe-set items this skill may auto-apply: adding documentation metadata
(plugin-data tags) and renaming an auto-named annotation layer it just created. Never auto-fix:
creating the kit components, creating annotation.* tokens, and (always) any change to the design being
documented. Fill policy: note/context cards are genuine surfaces → bind their bg to
color.annotation.surface; inner section boards are structural → fills = [].
10. State Management
Ledger under RUN_ID (shared/state-management.md), in storage.dh + an in-file breadcrumb:
phase, designBoardId, kit:{critiqueCardId,chipNoteId,pointerSId,pointerLId,tooltipId,created},
tokens:{accent,surface,...}, contextCardId, notesColumnX, groupId,
pins:[{n,regionId,pinId,noteId}], pinCounter. On resume: re-read the ledger, re-derive reality with
a structure read (the group + pins), and continue from pinCounter.
11. User Checkpoints
After phase
Artifacts shown
What we ask
0 discovery
design summary + pinnable regions + kit/token presence
Confirm target + kit plan?
1 brief
context-card content + numbered pin list
Approve brief + pins?
2 kit
proposed components + token names/values/tier (only if creating)
Approve kit + tokens?
3 context card
export_shape of the card
Approve content/placement?
each pin+note
export_shape of the region + note
Approve / adjust?
5 wrap & audit
hideable group + audit result
Approve handoff / iterate?
12. Naming Conventions
shared/naming-conventions.md. Components PascalCase (Critique Card, Chip Note, Pointer,
Tooltip — keep the reference system's names if reusing). Tokens dot-notation under an annotation
set (color.annotation.accent, font.annotation.label). Layers kebab-case/semantic
(context-card, note-card, pin, annotations); the hideable group keeps the recognizable name
Hide this to quit notes. Pin labels are the integer index.
13. Anti-Rationalization Table
Excuse the LLM makes
Why it's wrong
Deterministic countermeasure that halts the flow
"I'll just drop the note text on top of the design / recolor a layer to highlight it."
That mutates the deliverable; handoff annotations must be removable and non-destructive.
Stop. Add a sibling annotation shape in the notes column or a Pointer pin overlay; never edit an original shape. The Phase 5 audit fails if the design changed.
"I'll create all the pins and notes in one execute_code to save calls."
One-shot output is unauditable and de-syncs pin↔note numbering.
One annotation per call; checkpoint with export_shape; advance storage.dh.pinCounter each time.
"The accent blue is just decoration — hardcode #1A88E0."
Off-system values fail governance and won't theme/rebrand.
Bind to color.annotation.accent; if it doesn't exist, propose it (name/value/tier) for approval.
"This note doesn't really need a pin — it's general."
Orphan notes break the number→region reading model reviewers rely on.
Every Chip Note gets a Pointer pin on a concrete region; if it's truly global, it belongs in the context card, not a note.
"A plain text block is faster than instancing the Chip Note component."
Raw text drifts from the system and won't restyle with the kit.
Instance the kit component; if the kit is missing, create it once (under review) and reuse.
"I'll renumber notes later; order doesn't matter yet."
Gaps/dupes in numbering silently corrupt the handoff.
Keep numbering contiguous and matched at every step; the audit rejects gaps/dupes.
"I'll skip the hideable group; the layers are tidy enough."
Without one toggle, reviewers can't get back to the clean design.
Wrap all annotation shapes under the single Hide this to quit notes group before reporting done.