Wireframe Canvas
ASecurityBetween DESIGN.md and the scaffold, on every project with a UI: a screen inventory mapped to the PRD''s user stories, for public screens a page argument (an idea of the client''s own, a claim and proof per section), then every screen drawn as a desktop (1440) and a phone (390) artboard on a claude.ai Design canvas, in DESIGN.md with real copy, reviewed area by area. No scaffold until the user approves the canvas — `update_meta.py set-phase` refuses it. After approval, each artboard''s PNG is ...
- 6 stars
- 0 votes
- 0 copies
- 0 views
- Added October 19, 2026
Works with
Security analysis
100/100Pro scans all 6 files and shows the line behind each finding
npx -y skills add lukedj78/dev-flow --skill wireframe-canvas --agent claude-codeAre you the author of Wireframe Canvas?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/lukedj78-wireframe-canvas)---
name: wireframe-canvas
description: 'Between DESIGN.md and the scaffold, on every project with a UI: a screen inventory mapped to the PRD''s user stories, for public screens a page argument (an idea of the client''s own, a claim and proof per section), then every screen drawn as a desktop (1440) and a phone (390) artboard on a claude.ai Design canvas, in DESIGN.md with real copy, reviewed area by area. No scaffold until the user approves the canvas — `update_meta.py set-phase` refuses it. After approval, each artboard''s PNG is committed and commented on the tracker issues (Linear, Jira, GitHub) of its story. Writes `meta.json#wireframes`. Use when dev-flow routes here from `design_extracted`, or the user says "wireframe", "tutte le schermate", "disegna le schermate", "artboard", "canvas", "screen inventory", "mockup di ogni pagina". Not for: extracting a DESIGN.md (`figma-to-design-md`, `image-to-design-md`), building pages (`screenshot-to-page`, `rn-add-screen`), agent-only projects, or a canvas inside the product (`iframe-canvas`).'
---
# wireframe-canvas — every screen, drawn and approved, before any code
A standing rule of the user's (2026-10-10): **no feature code and no scaffold until every screen of
the product exists as an artboard and the user has approved the set.** A screen discovered while
coding costs a route, a layout and a review; on the canvas it costs a frame. And the issue tracker
gets the overall picture, so whoever picks up an issue sees the screen it builds.
## Contract
See `references/contracts.md` (vendored from `dev-flow`). Key facts:
- Reads `.workflow/PRD.md` (the `US-N` stories), `.workflow/tasks.md`, `.workflow/DESIGN.md`, `meta.json#stack`.
- Writes `docs/wireframes/screen-inventory.md`, `docs/wireframes/png/<ID>-desktop.png` / `<ID>-phone.png`,
and `meta.json#wireframes` through `scripts/wireframes.py` — never by hand.
- **Does not bump `phase`.** It appends `history`. The scaffold skill bumps it, and `set-phase` refuses
to cross into `monorepo_initialized` / `scaffolded` until `wireframes` is approved or skipped with a reason
(`dev-flow/scripts/wireframes_gate.py`). Projects already past `scaffolded` are not asked retroactively;
`show_state.py` flags them.
- Every stack with a UI: `next`, `expo-rn`, `monorepo`. **Refuses `framework: "agent"`** — no screens.
- Needs `DESIGN.md` first: the artboards are drawn in it, not in a placeholder grey.
## Step 1 — The screen inventory
`docs/wireframes/screen-inventory.md`: every route and screen of every epic, grouped by area (one `##`
per area, letter-prefixed), one table per area:
```markdown
## A — Public site
| ID | Screen | Route | Roles | Stories | States |
|---|---|---|---|---|---|
| A1 | Home (hero, search, featured trips) | `/` | visitor | US-6, US-48 | L |
| A2 | Destinations index | `/destinations` | visitor | US-55 | L, E |
```
- **ID** is stable (`A1`, `B12`): it names the artboards, the PNGs and the issue comments.
- **Stories** lists the PRD's `US-N`; **States** lists the ones the screen has — `L` loading, `E` empty,
`Er` error, `S` success — or `—`. Dialogs, sheets, banners and inline cards that change the flow are rows
too (Route `dialog`, `overlay`, `panel`).
- Walk the PRD story by story, then the roles (each role's home, settings, empty first run), then the
edges (auth, invite, legal, 404, offline on mobile).
Check it — every story maps to at least one screen, IDs are unique, no empty States cell:
```bash
python3 wireframe-canvas/scripts/wireframes.py coverage <root>
python3 dev-flow/scripts/update_meta.py <root> record-artifact --path docs/wireframes/screen-inventory.md \
--produced-by wireframe-canvas --derived-from .workflow/PRD.md
```
Show the user the inventory (counts per area, any story you were unsure about) before drawing.
## Step 1.5 — The page argument, when there are public screens
Every screen a person sees before signing in carries the role `visitor` in the inventory. If any row has it, write
`docs/wireframes/page-argument.md` before drawing that area: the
inventory of eight to twelve things only this client has, the idea sentence with the competitor test, one claim and
its proof per section (a section with no claim is cut), the optional live thing. Format, the why and the review
questions: **`references/page-argument.md`**. Check it:
```bash
python3 wireframe-canvas/scripts/wireframes.py argument <root>
```
Show it to the user with the inventory; the public area is drawn from it, section by section.
## Step 2 — The canvas, area by area
1. `Artifact action:"quickstart" intent:"design"` — it names the **Design** type and the design systems.
Create the canvas from that type, titled `<Project> · wireframes`, and follow the instructions the
create result returns for filling it. Do not guess the type's file format.
2. **One canvas page per area** of the inventory (`A — Public site`, `B — Authentication`, …).
3. **Two artboards per screen**: desktop **1440** wide and phone **390** wide, labelled
`<ID> · <Screen> · desktop` / `· phone`. The States column is drawn as well — extra artboards beside the
pair (`A2 · empty · phone`). The pair is the minimum the gate counts.
4. **High fidelity in DESIGN.md**: its colours, type scale, radius and spacing, and the primitives the
project will compose (golden rule 3) — a canvas that draws a component no primitive can become is a
promise the scaffold cannot keep. **Real copy in the user's language**, no lorem ipsum, realistic data.
**The board is the design; the primitive is tuned to it** (golden rule 3, «the primitive renders the
design»). Draw every component as the primitive it will be and name it in the layer (`Card · sm`,
`Button · outline`, `Badge · success`), but with the measures **the design** wants — and write every
measure that is not already in DESIGN.md into it (`rounded`, `components`: the card's radius, ring or
border, the selected chip's background, a button's weight and padding). A variant the board needs and
the library lacks goes into DESIGN.md's `components` block as it is drawn. That record is what the build
tunes the primitives' `cva` to, and verifies pixel by pixel against these artboards. **Why:**
smart-travel's boards drew cards at 16 px with a border against the Card's 12 px and ring and nobody
recorded it; first agents rebuilt the look by hand (84 hand-made div-cards), then a conversion to the
primitives used as they ship changed radii, selected backgrounds, weights and padding, and the user
rejected the screens (2026-10-12). After approval **the board changes only when the user decides to
change the design** — never to match what a primitive happens to render (§When the screens change later).
5. **Work one area at a time.** Finish an area, give the user the canvas link and the page, and stop for
their review. Before handing over a **public** area, put its artboards through the eight questions in
`references/page-argument.md` §Reviewing a public area and fix what fails — questions, not a score. Apply the changes; move on only when they say the area is right. Append a `history`
entry per reviewed area (`--skill wireframe-canvas --inputs '{"area": "A", "artboards": 26}'`).
## Step 3 — Approval
Only the user's own explicit yes for the **whole** canvas approves it. Then:
```bash
python3 wireframe-canvas/scripts/wireframes.py approve <root> --canvas-url <url> --user-said "<their words>"
```
It re-runs the coverage check, counts the screens, and refuses fewer than two artboards per screen
(`--artboards N` when the states add more). With public screens it also refuses an incomplete
`page-argument.md`; `--no-argument "<reason>"` records an exception in `meta.json#wireframes.argument` (the public
site is the client's existing one, the only public screen is a sign-in). In an autonomous run this is never derived: stop with
*"needs a human: approve the wireframe canvas"* and leave the canvas link.
**Opting out** is allowed and visible — a one-screen internal tool, a pure API with a status page:
```bash
python3 wireframe-canvas/scripts/wireframes.py skip <root> --reason "<why this project has no screens to draw>"
```
## Step 4 — After approval: screenshots on the issues
1. **Render a PNG of every artboard** at its native width (1440 / 390), by screenshotting the canvas in
a browser, into `docs/wireframes/png/<ID>-desktop.png` and `<ID>-phone.png`.
`wireframes.py pngs <root>` lists what is missing; it must print none.
2. **Commit them by name** (`git add docs/wireframes/`, never `git add -A`) and push. Note the commit SHA:
the image links are pinned to it, so a later edit of a PNG does not rewrite an old comment.
3. **Write the comment bodies** — one per issue whose user story (the `Stories` column, matched through the
task's epic heading, its `### US-N` heading or its own text in `tasks.md`) maps to a screen:
```bash
python3 wireframe-canvas/scripts/wireframes.py comments <root> --out .workflow/wireframe-comments \
[--repo <owner>/<name> --ref <sha>] # GitHub: the images are linked at that pinned commit
```
It prints the plan (issue → screens → body file). Show the user the count and one body, then post —
comments are posted on the user's behalf, so confirm once for the batch:
The issues come from `meta.json#tracker.issue_map` (the `scrum` skill's, keyed by `task_key`), so each body
is already named by its issue. **GitHub** `gh issue comment <n> --body-file <file>`, 2 s apart. **Linear** and
**Jira**: the body names the PNGs instead of linking them — attach them with the tracker's connector, then
comment the body. An old project with `.workflow/github-issues.json` can still pass `--map`.
4. Record it: `python3 wireframe-canvas/scripts/wireframes.py posted <root>` → `wireframes.screenshots_posted_at`.
Then hand back to dev-flow: `design-md-to-app` (web), `rn-bootstrap` (mobile), `monorepo-bootstrap`.
## When the screens change later
A new screen after approval is a new inventory row and a new artboard pair first, then code. Re-run
`approve` (same URL) so the counts are current, and comment the new PNGs on the issues they touch.
`screenshot-to-page` and `rn-add-screen` take the approved artboard PNG as their input, and verify the page
against it pixel by pixel; a difference is closed by tuning the primitive, not by editing the artboard. An
artboard changes only when the user decides to change the design — then re-render its PNG, re-run `approve`,
and update DESIGN.md if a measure changed.
The inventory has one more reader: `app-verification` seeds its feature map from it — one file per story, with
the screens, routes, roles and states listed here — so a row added here reaches the verification manual on its
next `scaffold`.
## Bundled
`scripts/wireframes.py` (`coverage`, `argument`, `approve`, `skip`, `pngs`, `targets`, `comments`, `posted`;
stdlib only) + `scripts/test_wireframes.py`; `references/page-argument.md` (the public page's argument and its
review questions); `references/contracts.md`. The gate itself is
`dev-flow/scripts/wireframes_gate.py`, so dev-flow enforces it without this skill installed.
Files in this skill
- SKILL.md
- references/contracts.md
- references/page-argument.md
- scripts/meta_io.py
- scripts/test_wireframes.py
- scripts/wireframes.py
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.