Install
$ agentstack add skill-yhassy-wireframe-skill-wireframe-skill ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
/wireframe
Generate a JSON wireframe definition and render it as a self-contained HTML preview.
Mode: Generate
Input
Two modes:
- Conversation: Describe the layout you want to wireframe. Claude generates JSON from the description.
- design-id argument:
wireframe {design-id}— readsdesigns/{design-id}/output/design-spec.mdand extracts layout structure from the Information Architecture section.
Output
Two files per screen:
{name}.wireframe.json— AI-readable wireframe definition{name}.wireframe.html— self-contained HTML preview (open in browser)
HTML preview features:
- Collapsible right panel showing live JSON (syncs on every edit)
- Drag-and-drop reordering within the same parent
- Save button (Chrome/Edge — uses File System Access API, first save opens picker, subsequent saves write directly)
- Copy JSON and Download JSON buttons (all browsers)
- Panel collapse state persists across sessions via localStorage
Output path:
- With design-id:
designs/{design-id}/output/wireframe/(automatic) - Without: prompted — ask user for directory path
Execution Steps
Step 1: Determine input
If a {design-id} argument is provided:
- Read
designs/{design-id}/output/design-spec.md - Extract layout structure from the Information Architecture section
- Identify all views/screens described
If no argument:
- Use the conversation context to understand the desired layout
- Ask clarifying questions if the layout description is ambiguous
Step 2: Load cognitive model and generate wireframe JSON
- Load the wireframe designer cognitive model from
.claude/skills/wireframe/wireframe-designer.md - Follow the perception sequence (Phases 1–7) to reason about the layout before producing JSON
- Produce a JSON object following the schema below
Schema rules (mechanical — these constrain the JSON format, not design judgment):
- Every node MUST have a
name - Layout containers MUST have
directionandchildren - Leaf elements SHOULD have a
type - The JSON maps 1:1 to CSS flexbox — think in flex terms
- Apply the sizing constraints from the Element types table. In particular: buttons, links, inputs, tags, and inline text must never have fixed
width— useheightonly and let content determine width
Step 3: Determine output location
Derive the filename from the JSON name field (slugified, e.g., "KAI 回答ビュー" → kai-answer-view).
If design-id was provided:
- Output directory is
designs/{design-id}/output/wireframe/(no prompt needed)
If no design-id:
- Ask the user where to save the JSON: "Where should I save the wireframe JSON? Provide a directory path."
- Use
AskUserQuestionwith a simple text prompt - Create the directory if it doesn't exist
Both .wireframe.json and .wireframe.html go in the same output directory.
Step 4: Generate HTML preview
Use a Bash command to splice the JSON into the template. This avoids outputting the ~1000-line template through the Write tool (which is slow because every line becomes output tokens):
python3 -c "
t = open('.claude/skills/wireframe/wireframe-template.html').read()
d = open('{json_path}').read()
open('{html_path}', 'w').write(t.replace('const WIREFRAME_DATA = null;', 'const WIREFRAME_DATA = ' + d + ';'))
"
Replace {json_path} and {html_path} with the actual output paths from Step 3. Use absolute paths.
Do NOT read the template with the Read tool or write the HTML with the Write tool. The Python script handles both file operations directly on disk.
Step 5: Output
- Write both
.wireframe.jsonand.wireframe.htmlfiles to the output directory from Step 3 - Open the HTML preview in the browser:
open {path}.wireframe.html - Confirm to the user:
``` Wireframe generated:
- JSON: {path}.wireframe.json
- Preview: {path}.wireframe.html (opened in browser)
```
JSON Wireframe Schema
{
"name": "Screen Name",
"viewport": { "width": 1280, "height": 800 },
"root": {
"name": "Root",
"direction": "vertical",
"children": []
}
}
Top-level fields
| Field | Type | Required | Description | |-------|------|----------|-------------| | name | string | Yes | Screen/wireframe name | | viewport | { width, height } | Yes | Canvas dimensions in px | | root | node | Yes | Root layout node |
Node fields
Identity:
| Field | Type | Required | Description | |-------|------|----------|-------------| | name | string | Yes | Node label (shown in wireframe) | | type | string | No | Element type for placeholder rendering | | variant | string | No | Text hierarchy: "display" (32px), "heading" (24px), "caption" (12px). Default body (16px). Only for type: "text". |
Layout (for containers with children):
| Field | Type | Default | CSS equivalent | |-------|------|---------|---------------| | direction | "vertical" / "horizontal" | "vertical" | flex-direction | | children | node[] | — | child elements | | gap | number | 0 | gap (px) | | padding | number or [v, h] | 0 | padding (px) | | justify | string | "flex-start" | justify-content | | align | string | "stretch" | align-items | | wrap | boolean | false | flex-wrap: wrap |
Sizing:
| Field | Type | Default | CSS equivalent | |-------|------|---------|---------------| | width | number | — | width (px) | | height | number | — | height (px) | | grow | boolean | false | flex: 1 | | maxWidth | number | — | max-width (px) |
Element types
| Type | Rendered as | Use for | Sizing | |------|------------|---------|--------| | "text" | Gray text label | Labels, headings, body text | height only. No width — text reflows naturally | | "image" | Gray box with image icon | Photos, thumbnails, hero images | width + height, or height + grow | | "icon" | Small gray circle | Action icons, status indicators | Fixed width + height always | | "button" | Rounded rectangle | CTAs, primary actions | height only. Never width — label length varies | | "link" | Underlined text | Navigation items, secondary actions, text links | height only. Never width — label length varies | | "input" | Bordered rectangle | Search fields, form inputs, dropdowns | height + grow or maxWidth. Never fixed width alone | | "card" | Bordered box with shadow | Content cards, list items | height + grow, or height alone in vertical lists | | "table" | Header row + placeholder data rows | Data tables, lists with columns | grow or omit. Column widths via columns[].width / columns[].grow | | "divider" | Thin horizontal line | Section separators | No sizing needed | | (none) | Transparent container | Structural grouping only | grow for flexible, width for fixed (e.g., sidebar) |
Table properties
Tables use columns and rows instead of children:
| Field | Type | Default | Description | |-------|------|---------|-------------| | columns | array | — | Column definitions (required for table) | | columns[].name | string | — | Column header text | | columns[].grow | boolean | false | Flexible width (flex: 1) | | columns[].width | number | — | Fixed width in px | | rows | number | 3 | Number of placeholder data rows |
{
"name": "Users Table",
"type": "table",
"columns": [
{ "name": "Name", "grow": true },
{ "name": "Email", "grow": true },
{ "name": "Role", "width": 120 },
{ "name": "Status", "width": 100 }
],
"rows": 5
}
Style properties (optional)
Visual properties for downstream consumers. These are purely additive — a wireframe JSON with zero style properties is 100% valid and renders as a monochrome wireframe (current behavior, unchanged). The wireframe HTML renderer ignores style properties.
The /wireframe skill itself produces plain wireframes. Style properties are added by /ui-prompts when a design system is specified, creating a "styled wireframe" that downstream consumers (pencil-generate, stitch-generate, Figma Make) use directly.
| Field | Type | Description | Applies to | |-------|------|-------------|------------| | fill | string (hex) | Background fill color | Containers, cards, buttons | | color | string (hex) | Text/icon foreground color | Text, icons, links | | fontSize | number | Font size in px | Text | | fontWeight | number | Font weight (400, 600) | Text | | borderRadius | number | Corner radius in px | Containers, cards, buttons, inputs | | stroke | { color, width } | Border definition | Containers, cards, inputs | | shadow | { x, y, blur, color } | Drop shadow | Containers, cards | | opacity | number (0–1) | Element opacity | Any node |
Rules:
- Values MUST be resolved (hex colors, px numbers) — never token names
- Absence means "use consumer defaults" — omit properties you don't need to specify
fillon a container = background;coloron text = foreground (avoid ambiguity)strokeandshadowuse object notation for clean parsing
Annotation fields:
| Field | Type | Description | |-------|------|-------------| | _solves | string | Traces this element to a PRD problem or user need. Metadata only — ignored by all renderers. |
Canonical schema: This JSON schema is the canonical layout format used across the pipeline. The ## Layout section in UI prompt files (prompts/*.md) uses this same schema inline, optionally with style properties. Skills that generate prompts (/ui-prompts, /style-exploration, /figma-variation) produce wireframe JSON. Skills that consume prompts (/pencil-generate, /stitch-generate) parse it directly.
Example
A dashboard with proper typographic hierarchy, spacing rhythm, and proportional heights:
{
"name": "Dashboard",
"viewport": { "width": 1280, "height": 800 },
"root": {
"name": "Page",
"direction": "vertical",
"children": [
{
"name": "Header",
"direction": "horizontal",
"height": 56,
"padding": [0, 24],
"justify": "space-between",
"align": "center",
"children": [
{ "name": "Logo", "type": "image", "width": 100, "height": 28 },
{ "name": "Search", "type": "input", "grow": true, "maxWidth": 400, "height": 40 },
{ "name": "Avatar", "type": "icon", "width": 32, "height": 32 }
]
},
{
"name": "Body",
"direction": "horizontal",
"grow": true,
"children": [
{
"name": "Sidebar",
"width": 240,
"direction": "vertical",
"padding": 16,
"gap": 4,
"children": [
{ "name": "Overview", "type": "link", "height": 40 },
{ "name": "Projects", "type": "link", "height": 40 },
{ "name": "Settings", "type": "link", "height": 40 }
]
},
{
"name": "Main",
"grow": true,
"direction": "vertical",
"padding": 32,
"gap": 24,
"children": [
{ "name": "Dashboard", "type": "text", "variant": "display", "height": 48 },
{
"name": "Stats Row",
"direction": "horizontal",
"gap": 16,
"children": [
{ "name": "Total Users", "type": "card", "grow": true, "height": 100 },
{ "name": "Revenue", "type": "card", "grow": true, "height": 100 },
{ "name": "Active Today", "type": "card", "grow": true, "height": 100 }
]
},
{
"name": "Recent Activity",
"direction": "vertical",
"gap": 12,
"children": [
{ "name": "Recent Activity", "type": "text", "variant": "heading", "height": 36 },
{
"name": "Activity Table",
"type": "table",
"columns": [
{ "name": "User", "grow": true },
{ "name": "Action", "grow": true },
{ "name": "Status", "width": 120 },
{ "name": "Time", "width": 140 }
],
"rows": 6
}
]
}
]
}
]
}
]
}
}
Cognitive reasoning behind this wireframe:
- Phase 3 (Task & Scanning): Dashboard = monitoring intent → F-pattern → top-to-bottom primary content flow, important information along left edge and top
- Phase 4 (Grid): Two major zones — sidebar (240px, fixed, persistent navigation) + content area (
grow: true). Sidebar exists because content inventory includes navigation that aids the monitoring task. - Phase 5 (Hierarchy): Three levels —
displayfor page identity ("Dashboard"),headingfor section identity ("Recent Activity"), body (default) for data content. Caption reserved for table column headers (chrome, not content). Sidebar nav useslink(navigation aids the task but isn't the task itself). Primary CTAs in the content area would usebutton. - Phase 6 (Spacing): Proximity tightens inward — root padding 32 > section gap 24 > card gap 16 > internal gap 12. Each step inward signals increasing relatedness. Container padding (32) ≥ child gap (24) everywhere.
- Phase 7 (Rhythm): Progressive density — spacious at top (title, 48px display text), medium in middle (stat cards, 100px), dense at bottom (table with 6 data rows). Heights accommodate content proportionally.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: yhassy
- Source: yhassy/wireframe-skill
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.