with one click
wireframe
Generate JSON wireframe with HTML preview
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Generate JSON wireframe with HTML preview
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Implement tasks from an OpenSpec change. Use when the user wants to start implementing, continue implementation, or work through tasks.
Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete.
Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use when the user wants to think through something before or during a change.
Propose a new change with all artifacts generated in one step. Use when the user wants to quickly describe what they want to build and get a complete proposal with design, specs, and tasks ready for implementation.
Enforce this repository's real Agent/Client foundation, TypeSpec-to-proto codegen, Next.js Client boundaries, and OpenSpec rules while editing code, docs, or tooling.
Premium UI/UX design audit and refinement skill. Use for design review, UI audit, visual polish, hierarchy, spacing, typography, color, responsive behavior, accessibility, consistency, and implementation-ready design plans. Purely visual; does not change product functionality or backend behavior.
| name | wireframe |
| description | Generate JSON wireframe with HTML preview |
Generate a JSON wireframe definition and render it as a self-contained HTML preview.
Two modes:
wireframe {design-id} — reads designs/{design-id}/output/design-spec.md and extracts layout structure from the Information Architecture section.One editable source and one generated preview per screen:
{name}.wireframe.json — the only editable wireframe source{name}.wireframe.html — self-contained generated HTML preview (open in browser, never edit)HTML preview features:
Output path:
designs/{design-id}/output/wireframe/ (automatic)If a {design-id} argument is provided:
designs/{design-id}/output/design-spec.mdIf no argument:
.opencode/skills/wireframe/wireframe-designer.mdSchema rules (mechanical — these constrain the JSON format, not design judgment):
namedirection and childrentypewidth — use height only and let content determine widthDerive the filename from the JSON name field (slugified, e.g., "KAI 回答ビュー" → kai-answer-view).
If design-id was provided:
designs/{design-id}/output/wireframe/ (no prompt needed)If no design-id was provided:
AskUserQuestion with a simple text promptBoth .wireframe.json and .wireframe.html go in the same output directory.
Generate the preview only from JSON with the repository generator:
node .opencode/skills/wireframe/scripts/generate-preview.mjs {json_path}
Replace {json_path} with the absolute JSON path from Step 3. The generator writes the matching .wireframe.html path.
Do NOT edit generated HTML. When rendering or design inspection reveals a problem, edit JSON and regenerate the preview.
.wireframe.json to the output directory from Step 3.wireframe.html preview with the repository generatoragent-browser open file://{absolute_path}.wireframe.htmlWireframe generated:
- JSON: {path}.wireframe.json
- Preview: {path}.wireframe.html (opened in browser)
{
"name": "Screen Name",
"viewport": { "width": 1280, "height": 800 },
"root": {
"name": "Root",
"direction": "vertical",
"children": []
}
}
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Screen/wireframe name |
viewport | { width, height } | Yes | Canvas dimensions in px |
root | node | Yes | Root layout node |
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) |
| 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) |
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
}
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:
fill on a container = background; color on text = foreground (avoid ambiguity)stroke and shadow use object notation for clean parsingCanonical schema: This JSON schema is the canonical layout format used across the pipeline. It describes only the visible layout. It is not a requirements-coverage, implementation, or internal-state artifact.
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": "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": "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:
grow: true). Sidebar exists only because persistent navigation is necessary for the monitoring task.display for page identity ("Dashboard"), heading for section identity ("Recent Activity"), body (default) for data content. Caption reserved for table column headers (chrome, not content). Sidebar nav uses link (navigation aids the task but isn't the task itself). Primary CTAs in the content area would use button.