# Design Build

> Build presentation decks, reports and web page layouts to an agency standard, from a source document. Use when asked to make, design or build a deck, presentation, pitch, slides, strategy document, report, whitepaper, one-pager, case study, landing page or web page layout — or to restyle, fix or improve an existing one. Front-loads art direction and structure so the work lands in one or two rounds instead of ten.

- Skill: `probot2004/design-build` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add probot2004/design-build`
- Raw SKILL.md: https://api.skillmd.com/api/skills/probot2004/design-build/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: PRoBoT2004 (https://skillmd.com/u/probot2004)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/probot2004/design-build

---


# design-build

Produce decks, reports and web layouts that read as designed rather than
assembled. The method is not "generate and refine" — it is **decide everything
that causes revision before rendering anything.**

## Why this exists

Three client decks in this system took 30, 50 and 76 rounds. Almost none of
those rounds were about content.

One 29-page brand deck was counted turn by turn off the transcript. **This is where the
rounds actually went, and every category is preventable:**

| Share | What the turn was | The gate that stops it |
|---|---|---|
| **20%** | An asset arriving one at a time — "i have added slide 3 internal image", ×7, plus 24 URLs across six turns | `manifest.py` — every frame named and requested **once**, before the build |
| **16%** | The user writing the art direction themselves, with ASCII wireframes and split percentages | Arrive with 2–3 real renders and a recommendation. A question is not a proposal. |
| **~13%** | A defect visible in the render — "it feels overlapping", "make all the cards same sizes", "its too conjusted", "that line is still there why?" | `lint.py` — measured, not eyeballed. Never send a render it has not passed. |

None of those needed taste. They needed a list, a proposal, and a measurement.

So the skill turns each silent decision into a question asked up front, gives
the answer a fixed vocabulary — 54 named layout patterns and 12 named
directions, so "something like this" becomes "C5" — and puts a **tool** in
front of the three failures above, because a rule that relies on remembering
is a rule that gets skipped on a deadline.

## The sequence

**Never skip steps 1–3 to get to rendering faster. That is the mistake this
skill exists to prevent.**

### 0 · Measure and research. Before anything else, and without being asked.

**Never design against your own taste when a number is available.**

```
python assets/measure.py <any reference>          # -> the numbers
python assets/measure.py <reference> --tokens     # -> brand.css
python assets/research.py --subject "..." --colour "..."   # -> a picked sheet
```

`measure.py` reads ground, ink, accent, corner radius, ink coverage,
dark-page ratio and the full type scale off any PDF, image or folder, and
scales the sizes to the canvas being built at. Run it on **every** reference
in the project folder before writing a line of CSS.

This step exists because a deck was once built to a catalogue while the
client's own reference sat unopened in the same repo, then rebuilt three
times on guesses — and every guess was a number readable off the file in ten
seconds. The ground was `#F0F0F0`, not white. The radius was 31px, not 8. The
display-to-body contrast was 8.2×, not 2.7×.

`research.py` builds its own keyword matrix and sweeps it. Generate the
vocabulary; do not wait to be handed it.

**The two sources want opposite words, and sending both the same query is why
sweeps come back generic:**

- **Pinterest = direction.** Indexed by how designers label their *own* work —
  "editorial spread", "type specimen", "grid system", "brand guidelines". This
  is the creative source, and it is creative *because of the vocabulary*.
  `--mode direction` (the default).
- **Freepik = asset.** A stock library, indexed by *literal subject nouns* —
  "scientist microscope laboratory". Design words return nothing here.
  `--mode asset`.
- **Neither = the specific requirement.** Their scene, this exact crop, the
  left third empty. That is `tools/imagegen.py`, which compiles the safe area,
  the measured aspect, the brand hex and the negative list into the prompt.
  Dry by default; `--go` spends credits, `--copy` emits the prompt alone.

**Banned search vocabulary** — *slide, template, powerpoint, infographic,
presentation, canva.* Measured: those words return template farms, which is the
aesthetic being escaped. Enforced in code, not advisory.

### 1 · Read the source completely

Transcribe the source document to `source_doc.txt` before designing. Count the
content blocks. Note every table, every set of numbers, every sequence — those
are already telling you their patterns.

### 2 · Intake — **one question at a time**

Work through `references/intake.md` in order, **one question per message**, not
nine in one. A wall of questions gets "just go" or three answers out of nine;
the other six come back as revisions. Each answer narrows the next, so later
questions get shorter — and Q3 needs no asking at all if Q2 produced a
reference.

Forced choice, defaults stated, and the moment the user shows they are busy:
stop asking, state the defaults being taken, and build.

Where art direction is at stake, **arrive with two or three real renders and a
recommendation.** 16% of turns on the last job were the user writing the art
direction themselves — that happens when what they were shown was not strong
enough to react to. A question is not a substitute for a proposal.

Two questions in that set are never skipped:

- **A supplied reference outranks the catalogue.** When the user sends a
  screenshot, board or competitor document, build to *that*, measured. Do not
  blend it with the catalogue or improve on it. This holds even when the
  reference arrives mid-build — rebuild the earlier pages to match rather than
  shipping a document in two languages.
- **Every screenshot gets the two-option question**: place it as-is, or rebuild
  its information as a native infographic. Ask per screenshot. Never decide it
  silently.

### 3 · Map, then gate

Assign a **pattern ID** from `references/patterns.md` to every page, using the
selection algorithm at the foot of that file. Set it as `data-id` on each
`<section class="slide">`.

Then run the **Contact Sheet Gate**:

```
python assets/sheet.py <deck>.html --wire
```

Every page renders as a wireframe — geometry, hierarchy, real content and the
brand's base colour, with the finish stripped — laid out as one numbered sheet
with each thumbnail labelled by pattern ID. The tool also prints the pattern map
and warns when the same pattern runs twice in a row.

Send the sheet. Get approval or corrections **on the sheet**, before building
anything at full fidelity.

This is the highest-leverage step in the process. It moves iteration from the
expensive end to the cheap end, and it makes the conversation *"page 7 is E3, it
should be D8"* instead of *"I don't like page 7."*

**Send the asset manifest in the same message as the sheet:**

```
python assets/manifest.py <deck>.html          # -> ASSETS-NEEDED.md
python assets/manifest.py <deck>.html --check  # what landed, what has not
python assets/manifest.py <deck>.html --stub   # grey on-grid placeholders
```

Every frame numbered, with the exact filename the build will look for, the
pixel size, what it must show, and which third stays clear for type. The
client drops one folder; nothing gets renamed or re-sent. This is the gate for
the largest single category of wasted turns.

### 4 · Build

Separate the concerns, always, into these files:

| File | Contains | Rule |
|---|---|---|
| `content.py` | every string, from the source | **Sacred.** Nothing authored here. One source for all cuts — never forked. |
| `build.py` | layout only — which pattern each block gets, and where | |
| `deck.css` | the design system | |
| `render.py` | HTML → PNG + PDF | |
| `preview.py` | one page, for tuning | |
| `audit.py` | dropped/added phrase check, both directions | |

### 5 · Lint — **never send a render this has not passed**

```
python assets/lint.py <deck>.html
```

Measures what the client would otherwise measure by looking: boxes that
intersect, siblings whose sizes disagree by a near-miss, type under the 17px
floor, content off the canvas, ink coverage over the congestion threshold, and
headlines sitting on the loud part of a photograph. Furniture is auto-detected
by its recurrence and exempted, so the rail does not get flagged 29 times.

Every check in it exists because a real client sentence is quoted beside it —
*"it feels overlapping"*, *"make all the cards same sizes"*, *"its too
conjusted"*, *"that line is still there why?"* A defect found here costs
seconds. The same defect found by the client costs a round.

**Fails block the PDF. Warnings get read, not ignored.**

### 6 · Audit and measure

Run the content audit both directions. Then measure the design:
ink coverage, accent percentage, type-size distribution, and **how many pages
share a composition**. Numbers catch monotony that the eye rationalises.

## References

| File | Read it when |
|---|---|
| `references/intake.md` | Before every project, without exception |
| `references/patterns.md` | Assigning a layout to every content block |
| `references/directions.md` | Choosing the art direction at intake |
| `references/imagery.md` | Deciding what goes in any frame — photo, screenshot, abstract, or nothing |
| `references/craft.md` | Writing CSS — the defect list and the rendering traps |
| `assets/` | Building. `tokens.css` + `patterns.css` are the working system; `gallery.py` holds the markup for all 54; `render.py` builds the contact sheet. |

### The tools, and the failure each one exists to stop

| Tool | Stops |
|---|---|
| `assets/measure.py` | Designing against taste when a number is readable off the reference |
| `assets/research.py` | Generic sweeps — Pinterest for direction, Freepik for assets, never the same words to both |
| `tools/imagegen.py` | Stock standing in for a specific requirement; artwork that fills the third the headline needs |
| `assets/manifest.py` | Assets arriving one at a time. **The largest single category of wasted turns.** |
| `assets/sheet.py` | Full-fidelity rebuilds of structural mistakes |
| `assets/lint.py` | Sending a render with defects a measurement would have caught |
| `audit.py` (per deck) | Content silently dropped or authored |

Every pattern ID in `references/patterns.md` has a matching class in
`assets/patterns.css` and working markup in `assets/gallery.py`. Copy from
there rather than writing a layout from scratch — the geometry is already
measured and the defects are already fixed.

## The rules — and which register they belong to

**These were calibrated on a dense consulting report. Half of them are wrong
for a product deck, and shipping them unchanged is how a sales deck ends up
reading like a Word document.** Measure the reference first (step 0); when a
measured number disagrees with a rule below, the number wins.

| | **Report / strategy** | **Product / sales** |
|---|---|---|
| Ground | white, dark ≤20% | light system, dark **inverted** on the pages where the argument turns — cover, the reveal, dividers, closer. ~25–30% is correct. |
| Headline | 56px, weight 400 | **82–199px, weight 800.** Display-to-body contrast 6–8×, not 2.7×. |
| Body | 21px | **24–30px** |
| Corner radius | 0–8px, hairlines | **18–31px**, soft layered shadows, real depth |
| Enclosure | hairlines before borders before fills | cards with fills and depth; a hairline reads as unfinished here |
| Imagery | covers, dividers, closers only | **every page**, composed individually — placed and bleeding, never a strip in the same position twice |
| Accent | ≤2% of pixels, ink only | large fields, gradients, one filled "hot" tile per comparison |

### What holds in both

1. **Furniture on 100% of pages**, identical position. The cheapest way to
   prove a system exists.
2. **Type floor 17px @1920.** Timid small type reads as unfinished, not
   restrained.
3. **Every content block resolves to a table, chart, timeline, list or stat
   grid.** If the source shows it as a table, it stays a table.
4. **Never the same composition twice in a row** — unless the pages are a
   declared matched pair.
5. **A real image cropped to the grid, or nothing.** Never a dashed
   placeholder. Abstract earns its place only when it *is* the information, or
   when the brand already owns the visual system.
6. **Nothing bright in the corner a headline occupies.** Content starts at
   y≈70; artwork placed there is illegible regardless of opacity.
7. **Compute the stage width against the artwork** — `live width − band − 70`.
   Eyeballing it puts text under the image.
8. **Content is sacred.** Dropping a word to make a number look better
   ("Only 7%" → "7%") is a content change. The audit catches it; run it.

## Never do these

Learned by having them rejected on real work:

- Serif headline swaps and logo watermarks introduced as "improvement." An
  improvement adds information or fixes a defect. Anything else is a designer
  signature on someone else's brand, and it gets rejected.
- Abstract generated shapes as image placeholders.
- A second accent colour the brand system doesn't have.
- Numbered version folders. One folder, rebuilt in place — git holds history.

