CommunityImagegithub.com

lw-spec-mockup

Use when a spec or a plan needs a picture of a screen, a state, a dialog, a console page or a flow, when the user asks "where is the design", "draw it" or "show every state", and before you commit or change a board in docs/specs/assets. Draws generated SVG boards with one library. Not for the spec text, which is lw-spec-write.

What is lw-spec-mockup?

lw-spec-mockup is a Claude Code agent skill that use when a spec or a plan needs a picture of a screen, a state, a dialog, a console page or a flow, when the user asks "where is the design", "draw it" or "show every state", and before you commit or change a board in docs/specs/assets. Draws generated SVG boards with one library. Not for the spec text, which is lw-spec-write.

Works with✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/launchwrighthq/agent-harness/tree/HEAD/skills/lw-spec-mockup

Installed? Explore more Image skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Spec mockups

This skill says how to draw. lw-spec-write says where the spec goes and how the page renders.

Product facts

The adapter folder comes from the config. Read it first:

ah config get harness.adapterDir

Then read <adapterDir>/spec-mockup/. The project owns it. It names:

FactExample
The token files of each app, in orderapps/console/src/styles/tokens.css
The selectors of the light and the dark values:root, .dark
The lucide icon foldernode_modules/lucide-react/dist/esm/icons
The navigation of each app with a sidebar, and where it comes fromthe route table of the console
The source of real copythe i18n catalogue of the app

When the adapter is missing, ask the user for the token file before you draw. Never invent a colour.

The format

Generated SVG, drawn with one library: boards.py beside this file. Each spec has one script, docs/specs/assets/<date>-<topic>-boards.py. It imports the library and writes into docs/specs/assets/<date>-<topic>/. Never edit a generated SVG by hand: change the script and run it again. When the library lacks a piece, add it to the project's own helper module beside the script, so the next spec has it too.

example.py is a worked board: a page on desktop and on a phone, with pins and a legend. Run it to see the shape:

python3 .claude/skills/lw-spec-mockup/example.py <scratchpad>/mock --render

A spec script starts like this:

import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[3]
sys.path.insert(0, str(ROOT / ".claude/skills/lw-spec-mockup"))
from boards import GUTTER, Board, render, tokens

t = tokens("apps/console/src/styles/tokens.css", "light")
b = Board(1440 + 2 * GUTTER, 1200, icons="node_modules/lucide-react/dist/esm/icons")
b.title("Dashboard: the empty state")
f = b.sidebar_app(
    GUTTER,
    160,
    t["bg"],
    t["sidebar"],
    t["ink"],
    t["muted"],
    t["active"],
    ["Dashboard"],
    "Dashboard",
    "Console",
)
b.pin(f.x + f.left + 24, f.top + 30, 1)
b.legend(
    GUTTER, 1100, [(1, "The empty state", "No widget until the product names one.", "R1")], 1440
)
b.save("docs/specs/assets/<date>-<topic>/desktop-empty.svg")
CallDraws
tokens(files, theme, base=, dark=, overlay=)The resolved --* values of the token files. t["accent"]. A missing token raises. overlay is a proposed restyle
phone(x, y, bg, ink, surface, url), desktop(x, y, bg, url)A phone (web or app), a browser window
sidebar_app(x, y, ...)An app with a left sidebar, such as a console. Copy nav from the app's route table
screenshot(path, x, y), crop(path, ...)A real capture of the shipped screen, or a region of it, for the Today column
icon(name, x, y, size, color)A lucide glyph from the board's icons folder
image(path, ...), embed_font(family, path)Real art and a brand face from the repository
pin, legend, caption, column_head, row_label, titleThe notes. A legend note longer than two lines raises
render(svg, png, w, h)The headless Chrome screenshot for the check below

Fidelity

  • Colours are tokens, through tokens(). A hex value in a spec script is wrong, except for art that the token file does not hold.
  • Copy is real. Use the string of the app's catalogue when it exists. A new string is short: a label, a value, an empty state, an error or a one-line hint.
  • Data is realistic. Use plausible values, and a long one where one can occur.

Canvas

SurfaceFrame
Phone390 x 844, 48 px gutters
Desktop1440 x 900
Boardas wide as its frames, as high as its rows need

What a spec draws

  1. Today, then target. "Today" is a real screenshot of the shipped screen (today-*.png). "Target" is the SVG. Put them side by side in a Markdown table.
  2. One row per state that applies: default, empty, loading, error, long text, the smallest and the largest content.
  3. Pins and a legend. A numbered pin on each element that changes. Under the frame, a numbered legend: a bold head, two lines at most, and the spec ID it serves.
  4. A component list in the spec beside the boards: each element, the component it reuses, and each new component with its reason.

Names

docs/specs/assets/<YYYY-MM-DD>-<topic>-boards.py
docs/specs/assets/<YYYY-MM-DD>-<topic>/<surface>-<state>.svg
docs/specs/assets/<YYYY-MM-DD>-<topic>/today-<surface>-<state>.png

The spec names the basename of every file it holds in assets/.

Look at every board before you commit it

A defect of a board is invisible in its source and clear in the picture. Render each board and read the PNG with the Read tool. Write the PNG to the scratchpad, not to docs/.

  • No text runs past its frame, and no pin covers a value.
  • Each string in the drawn UI is a label, a value, an empty state, an error or a hint.
  • No placeholder art, and no colour picked by eye.
  • Each state and surface that the spec touches has its frame.
  • Today and target sit side by side.

render needs google-chrome or chromium on PATH.

After the build

The build must match the approved board. Capture the built screen and put it beside the board. A difference is a defect of the build, not a reason to draw the board again.

Related Skills