Image(s) → DESIGN.md
Take 1 or more raster images (PNG / JPG) and produce a DESIGN.md that conforms to the Google design.md spec. The same workflow used in figma-to-design-md Path C (manual fallback) is the default here, since raster is all we have.
When this skill applies
Trigger on any of:
- The user pastes 1+ image paths and asks for a design system / DESIGN.md.
- The user describes images they have (Pinterest pins, Dribbble shots, competitor screenshots, hand-drawn mockups, scanned printouts).
- An explicit request: "estrai design da queste immagini", "make a DESIGN.md from this image", "build a design system from this Figma export PNG".
- The orchestrator (
dev-flow) routes here from phase prd_drafted or empty when the user has no Figma URL but has images.
If the user has BOTH a Figma URL AND images, prefer figma-to-design-md (more precise — Variables panel beats vision LLM) and pass the images to screenshot-to-page later.
What you produce
In dev-flow mode: <root>/.workflow/DESIGN.md + <root>/.workflow/screenshots/<slug>.png for each input image.
In standalone mode: <project-root>/DESIGN.md + <project-root>/screenshots/.
The DESIGN.md follows the same 8-section structure as figma-to-design-md produces — same spec — see references/spec.md for the canonical Google design.md spec.
Dev-flow contract
This skill participates in the dev-flow workflow. See references/contracts.md for the canonical schema. Key facts:
- Output goes into
<root>/.workflow/:
DESIGN.md (the main artifact)
screenshots/ (input images copied + slugged)
- State is updated by setting
meta.json#phase = "design_extracted" (only if the current phase is earlier in the enum), refreshing updated_at, and appending a history entry.
- Standalone mode (no
.workflow/ present) is supported — fall back to writing at the user-specified project root.
Prerequisites
- Vision-capable LLM. This skill leans on the model's vision capability for typography identification, component recognition, and layout inference. Claude Opus/Sonnet/Haiku 4.5+ all qualify; ChatGPT-4o and Gemini also work in their respective harnesses.
- Python 3.10+ with Pillow + numpy + scikit-learn (only for
quantize_palette.py).
If neither vision nor Python is available, this skill cannot run — refuse and explain. Don't fabricate token values.
Workflow
Step 1 — Locate the images and the output directory
- The user provides one or more image paths (absolute or relative to cwd). Validate each: exists, is a readable file, has extension
.png / .jpg / .jpeg / .webp / .bmp.
- Dev-flow mode: if
<cwd>/.workflow/meta.json exists, output goes into <cwd>/.workflow/. Read meta.json#project_name and PROJECT.md (if present) for brand context.
- Standalone mode: identify the project root (current working directory unless user says otherwise). Output goes there as
DESIGN.md + screenshots/.
- If a
DESIGN.md already exists at the target, ask before overwriting.
Step 2 — Capture brand context
The images alone don't tell you "what this brand is for". Ask the user for, at minimum:
- Project name (used as
name: in the frontmatter and as the slug for screenshot filenames).
- Audience / use-case (1–2 sentences). Used to write the Overview section.
- Voice / tone if obvious — playful, editorial, austere, etc.
If PROJECT.md exists in .workflow/, reuse it: it already answers most of these.
Step 3 — Extract the palette via k-means
For each input image:
- Run
python3 scripts/quantize_palette.py <image-path> --k 12 --no-crop to get the top 12 dominant colors.
- The script returns
(hex, percentage) pairs. Don't take all 12 blindly — filter:
- Drop pure-grays unless they're explicitly a UI surface color.
- Drop colors that appear only in photographic content (skin tones, sky, foliage). These are content, not brand.
- Cluster near-duplicates (Δhex < 8 per channel).
When you have multiple images, run scripts/aggregate_palettes.py <img1> <img2> … to merge their palettes into a single deduped list ranked by total weighted frequency. This handles the case "5 screenshots of the same app" where the brand palette repeats across images — the cross-image-recurring colors are the real tokens; one-off colors are noise.
Map the surviving colors to spec-recommended names: primary, secondary, tertiary, neutral, surface, on-surface, error (per the spec's "Recommended Token Names"). When in doubt about which color is primary, ask the user — typically it's the most saturated brand-distinct color, NOT the one that takes the most pixels (white usually wins on pixel count).
Step 4 — Identify typography
This is the highest-confidence-loss step. Vision LLMs can identify a font family within a small set of candidates but cannot read fontFamily metadata that doesn't exist in raster pixels.
For each image:
- Identify text regions and their visual hierarchy (display headline, body, caption, button label, …).
- For each tier, estimate:
- Family: name 1–3 likely candidates. If the font is clearly proprietary (Söhne, Roobert, Wise Sans, Helvetica Now, Cera Pro, GT Walsheim, Brown, Söhne Breit), name it AND a Google Fonts open-source fallback (Inter, Manrope, DM Sans, IBM Plex Sans). The DESIGN.md should emit the fallback as
fontFamily and document the proprietary original in the prose.
- Size: estimate from pixel height of cap-letters relative to known image dimensions. Use designer-friendly numbers (12, 14, 16, 18, 20, 24, 32, 40, 48, 64, 72, 96, 126).
- Weight: identify from stroke thickness — typical buckets are 400 (regular), 500 (medium), 600 (semibold), 700 (bold), 900 (black).
- Line-height: estimate from spacing between lines.
- Letter-spacing: estimate, expressed in
em (positive ≈ tracked, negative ≈ tight).
State the confidence level explicitly in the prose: display-lg: Inter 96/0.9/900 (visually identified — original may be Söhne Breit, swap if available).
Step 5 — Identify components
For each image, scan for recurring UI patterns:
- Buttons: shape (pill / rounded / sharp), fill color, text color, padding hint, hover-state if visible.
- Cards: radius (sharp ≈ 4px, soft ≈ 12–16px, generous ≈ 24–40px, mega ≈ 9999px-pill — eyeball it), surface color, border presence.
- Inputs: radius, fill, border treatment, error state if any.
- Navigation: top-bar / sidebar / mixed. Active-item style.
- Badges / chips: shape, color mapping (status-driven? semantic?).
Map each to the components block in the frontmatter. Don't invent variants you don't see — if only the default state is visible, emit only the default. Variants get added later by screenshot-to-page when more images arrive.
Step 6 — Identify layout, shapes, elevation
- Layout: grid model (single-column / 2-col / 12-col / asymmetric mosaic). Container max-width if visible. Spacing rhythm if you can read it (4 / 8 / 16 px clusters).
- Shapes: corner-radius scale (collect distinct radii observed). Map to
rounded tokens (sm/md/lg/full).
- Elevation: drop-shadows? ring borders? tonal layers? For each card-like surface, decide.
- Brand voice prose: synthesize the Overview section from the user's audience input + observed visuals. 4-6 sentences.
Step 7 — Synthesize and write the DESIGN.md
Assemble the frontmatter (colors / typography / rounded / spacing / components) + 8 prose sections (Overview / Colors / Typography / Layout / Elevation & Depth / Shapes / Components / Do's and Don'ts) per the spec.
Validate before writing:
- Frontmatter delimited with
--- lines.
- All color values are
"#rrggbb".
- All dimensions use
px, em, or rem.
- All
{path.to.token} references resolve.
- 8 sections in spec order, no duplicates.
colors.primary is defined (mandatory).
Write to <root>/.workflow/DESIGN.md (dev-flow) or <project-root>/DESIGN.md (standalone).
Step 8 — Copy images to screenshots/
Each input image is copied into <root>/.workflow/screenshots/<slug>.png so:
- Future
screenshot-to-page invocations can use them as references.
- The DESIGN.md prose can cite them: "Pattern observed in
screenshots/dashboard.png".
Slug each filename: lowercase, replace non-alphanumeric with hyphens, ensure uniqueness.
Step 9 — Update state and report
Dev-flow mode: before reporting, update <root>/.workflow/meta.json:
- if current
phase is earlier than design_extracted, set phase = "design_extracted".
- bump
updated_at to ISO-8601 UTC now.
- append a
history entry:{
"skill": "image-to-design-md",
"ran_at": "<now>",
"inputs": {"image_count": <n>, "images": ["<paths>"]},
"outputs": ["DESIGN.md", "screenshots/"],
"phase_before": "<prev>",
"phase_after": "design_extracted"
}
Then tell the user, briefly:
- Number of images analyzed.
- How many color / typography / component tokens you extracted.
- Confidence per section (palette: high; typography: medium-low; components: medium).
- Sections you flagged as low-confidence and would benefit from human input.
- Where the file was saved.
- In dev-flow mode: the new phase and the next-step proposal (
design-md-to-app to scaffold the codebase).
Important constraints
- Don't invent values you don't have evidence for. If only one image is supplied and it doesn't show typography, emit a stub
typography: block with a prominent note in the prose, OR ask the user for one extra image showing text. Don't fabricate.
- Be explicit about font names. Vision can't read embedded font metadata; everything is a guess. Always name a Google Fonts fallback and mention the likely original in prose.
- Don't try to identify dark/light modes from a single image. If the image is dark-themed, generate the dark variant; auto-derive light only if the user requests.
- Don't store images outside
screenshots/. Skills downstream expect them there.
- Don't process images larger than ~10 MB without warning the user — k-means on a 4K image is slow.
- Per la lingua delle prose: la skill scrive le sezioni in inglese di default. Se il
PROJECT.md o l'input utente è in italiano, la skill rispetta la lingua dell'utente per la prosa (frontmatter resta in formato spec — nomi token in inglese).
Quality bar — what a good output looks like
- Palette section: 8–15 named tokens with prose justification ("primary
#7839CD reserved for the load-bearing CTA"). No "color1 / color2" placeholder names.
- Typography section: 6+ levels with samples that read as real product copy (extracted from PRD.md if available, or asked from the user). NEVER use
Lorem ipsum or "Body 16/400/regular" as samples.
- Confidence flags: every section that contains a guess is marked. Future agents reading the DESIGN.md should know what to trust.
- Screenshot citations: the prose references
screenshots/<file> for any inferred-from-image claim.
A good DESIGN.md from this skill is one that the user can read, agree with, edit a few prose lines, and ship — not one they have to rewrite.
1---2name: image-to-design-md3description: Generate a DESIGN.md (Google design.md spec) from 1+ raster images — PNG / JPG screenshots, mockups, Pinterest pins, Dribbble shots, competitor app captures. Extracts palette via k-means, identifies typography + components via vision-LLM, infers layout / radius / spacing, synthesizes a spec-compliant DESIGN.md + copies images to `screenshots/`. Use whenever the user provides 1+ images and asks to generate / extract / build a DESIGN.md / design system / design tokens — even phrased loosely like "estrai design da queste immagini", "make a DESIGN.md from this mockup", "design system from these screenshots". Not for: Figma files (use `figma-to-design-md`), code scaffolding (use `design-md-to-app` after), or single-page generation (use `screenshot-to-page` after the project is scaffolded).4---56# Image(s) → DESIGN.md78Take 1 or more raster images (PNG / JPG) and produce a `DESIGN.md` that conforms to the Google design.md spec. The same workflow used in `figma-to-design-md` Path C (manual fallback) is the **default** here, since raster is all we have.910## When this skill applies1112Trigger on any of:13- The user pastes 1+ image paths and asks for a design system / DESIGN.md.14- The user describes images they have (Pinterest pins, Dribbble shots, competitor screenshots, hand-drawn mockups, scanned printouts).15- An explicit request: "estrai design da queste immagini", "make a DESIGN.md from this image", "build a design system from this Figma export PNG".16- The orchestrator (`dev-flow`) routes here from phase `prd_drafted` or `empty` when the user has no Figma URL but has images.1718If the user has BOTH a Figma URL AND images, prefer `figma-to-design-md` (more precise — Variables panel beats vision LLM) and pass the images to `screenshot-to-page` later.1920## What you produce2122In **dev-flow mode**: `<root>/.workflow/DESIGN.md` + `<root>/.workflow/screenshots/<slug>.png` for each input image.23In **standalone mode**: `<project-root>/DESIGN.md` + `<project-root>/screenshots/`.2425The DESIGN.md follows the same 8-section structure as `figma-to-design-md` produces — same spec — see `references/spec.md` for the canonical Google design.md spec.2627## Dev-flow contract2829This skill participates in the dev-flow workflow. See `references/contracts.md` for the canonical schema. Key facts:3031- **Output** goes into `<root>/.workflow/`:32 - `DESIGN.md` (the main artifact)33 - `screenshots/` (input images copied + slugged)34- **State** is updated by setting `meta.json#phase = "design_extracted"` (only if the current phase is earlier in the enum), refreshing `updated_at`, and appending a `history` entry.35- **Standalone mode** (no `.workflow/` present) is supported — fall back to writing at the user-specified project root.3637## Prerequisites3839- **Vision-capable LLM**. This skill leans on the model's vision capability for typography identification, component recognition, and layout inference. Claude Opus/Sonnet/Haiku 4.5+ all qualify; ChatGPT-4o and Gemini also work in their respective harnesses.40- **Python 3.10+** with Pillow + numpy + scikit-learn (only for `quantize_palette.py`).4142If neither vision nor Python is available, this skill cannot run — refuse and explain. Don't fabricate token values.4344## Workflow4546### Step 1 — Locate the images and the output directory4748- The user provides one or more image paths (absolute or relative to cwd). Validate each: exists, is a readable file, has extension `.png` / `.jpg` / `.jpeg` / `.webp` / `.bmp`.49- **Dev-flow mode**: if `<cwd>/.workflow/meta.json` exists, output goes into `<cwd>/.workflow/`. Read `meta.json#project_name` and `PROJECT.md` (if present) for brand context.50- **Standalone mode**: identify the project root (current working directory unless user says otherwise). Output goes there as `DESIGN.md` + `screenshots/`.51- If a `DESIGN.md` already exists at the target, ask before overwriting.5253### Step 2 — Capture brand context5455The images alone don't tell you "what this brand is for". Ask the user for, at minimum:56571. **Project name** (used as `name:` in the frontmatter and as the slug for screenshot filenames).582. **Audience / use-case** (1–2 sentences). Used to write the **Overview** section.593. **Voice / tone** if obvious — playful, editorial, austere, etc.6061If `PROJECT.md` exists in `.workflow/`, reuse it: it already answers most of these.6263### Step 3 — Extract the palette via k-means6465For each input image:66671. Run `python3 scripts/quantize_palette.py <image-path> --k 12 --no-crop` to get the top 12 dominant colors.682. The script returns `(hex, percentage)` pairs. Don't take all 12 blindly — filter:69 - Drop pure-grays unless they're explicitly a UI surface color.70 - Drop colors that appear only in photographic content (skin tones, sky, foliage). These are content, not brand.71 - Cluster near-duplicates (Δhex < 8 per channel).7273When you have **multiple images**, run `scripts/aggregate_palettes.py <img1> <img2> …` to merge their palettes into a single deduped list ranked by total weighted frequency. This handles the case "5 screenshots of the same app" where the brand palette repeats across images — the cross-image-recurring colors are the real tokens; one-off colors are noise.7475Map the surviving colors to spec-recommended names: `primary`, `secondary`, `tertiary`, `neutral`, `surface`, `on-surface`, `error` (per the spec's "Recommended Token Names"). When in doubt about which color is `primary`, ask the user — typically it's the most saturated brand-distinct color, NOT the one that takes the most pixels (white usually wins on pixel count).7677### Step 4 — Identify typography7879This is the highest-confidence-loss step. Vision LLMs can identify a font family within a small set of candidates but **cannot read fontFamily metadata that doesn't exist in raster pixels**.8081For each image:82831. Identify text regions and their visual hierarchy (display headline, body, caption, button label, …).842. For each tier, estimate:85 - **Family**: name 1–3 likely candidates. If the font is clearly proprietary (Söhne, Roobert, Wise Sans, Helvetica Now, Cera Pro, GT Walsheim, Brown, Söhne Breit), name it AND a Google Fonts open-source fallback (Inter, Manrope, DM Sans, IBM Plex Sans). The DESIGN.md should emit the **fallback** as `fontFamily` and document the proprietary original in the prose.86 - **Size**: estimate from pixel height of cap-letters relative to known image dimensions. Use designer-friendly numbers (12, 14, 16, 18, 20, 24, 32, 40, 48, 64, 72, 96, 126).87 - **Weight**: identify from stroke thickness — typical buckets are 400 (regular), 500 (medium), 600 (semibold), 700 (bold), 900 (black).88 - **Line-height**: estimate from spacing between lines.89 - **Letter-spacing**: estimate, expressed in `em` (positive ≈ tracked, negative ≈ tight).9091State the confidence level explicitly in the prose: `display-lg: Inter 96/0.9/900 (visually identified — original may be Söhne Breit, swap if available)`.9293### Step 5 — Identify components9495For each image, scan for recurring UI patterns:9697- **Buttons**: shape (pill / rounded / sharp), fill color, text color, padding hint, hover-state if visible.98- **Cards**: radius (sharp ≈ 4px, soft ≈ 12–16px, generous ≈ 24–40px, mega ≈ 9999px-pill — eyeball it), surface color, border presence.99- **Inputs**: radius, fill, border treatment, error state if any.100- **Navigation**: top-bar / sidebar / mixed. Active-item style.101- **Badges / chips**: shape, color mapping (status-driven? semantic?).102103Map each to the `components` block in the frontmatter. **Don't invent variants you don't see** — if only the default state is visible, emit only the default. Variants get added later by `screenshot-to-page` when more images arrive.104105### Step 6 — Identify layout, shapes, elevation106107- **Layout**: grid model (single-column / 2-col / 12-col / asymmetric mosaic). Container max-width if visible. Spacing rhythm if you can read it (4 / 8 / 16 px clusters).108- **Shapes**: corner-radius scale (collect distinct radii observed). Map to `rounded` tokens (`sm/md/lg/full`).109- **Elevation**: drop-shadows? ring borders? tonal layers? For each card-like surface, decide.110- **Brand voice prose**: synthesize the **Overview** section from the user's audience input + observed visuals. 4-6 sentences.111112### Step 7 — Synthesize and write the DESIGN.md113114Assemble the frontmatter (colors / typography / rounded / spacing / components) + 8 prose sections (Overview / Colors / Typography / Layout / Elevation & Depth / Shapes / Components / Do's and Don'ts) per the spec.115116Validate before writing:117118- Frontmatter delimited with `---` lines.119- All color values are `"#rrggbb"`.120- All dimensions use `px`, `em`, or `rem`.121- All `{path.to.token}` references resolve.122- 8 sections in spec order, no duplicates.123- `colors.primary` is defined (mandatory).124125Write to `<root>/.workflow/DESIGN.md` (dev-flow) or `<project-root>/DESIGN.md` (standalone).126127### Step 8 — Copy images to screenshots/128129Each input image is copied into `<root>/.workflow/screenshots/<slug>.png` so:130- Future `screenshot-to-page` invocations can use them as references.131- The DESIGN.md prose can cite them: "Pattern observed in `screenshots/dashboard.png`".132133Slug each filename: lowercase, replace non-alphanumeric with hyphens, ensure uniqueness.134135### Step 9 — Update state and report136137**Dev-flow mode:** before reporting, update `<root>/.workflow/meta.json`:138- if current `phase` is earlier than `design_extracted`, set `phase = "design_extracted"`.139- bump `updated_at` to ISO-8601 UTC now.140- append a `history` entry:141 ```json142 {143 "skill": "image-to-design-md",144 "ran_at": "<now>",145 "inputs": {"image_count": <n>, "images": ["<paths>"]},146 "outputs": ["DESIGN.md", "screenshots/"],147 "phase_before": "<prev>",148 "phase_after": "design_extracted"149 }150 ```151152**Then tell the user, briefly:**153- Number of images analyzed.154- How many color / typography / component tokens you extracted.155- Confidence per section (palette: high; typography: medium-low; components: medium).156- Sections you flagged as low-confidence and would benefit from human input.157- Where the file was saved.158- In dev-flow mode: the new phase and the next-step proposal (`design-md-to-app` to scaffold the codebase).159160## Important constraints161162- **Don't invent values you don't have evidence for.** If only one image is supplied and it doesn't show typography, emit a stub `typography:` block with a prominent note in the prose, OR ask the user for one extra image showing text. Don't fabricate.163- **Be explicit about font names.** Vision can't read embedded font metadata; everything is a guess. Always name a Google Fonts fallback and mention the likely original in prose.164- **Don't try to identify dark/light modes from a single image.** If the image is dark-themed, generate the dark variant; auto-derive light only if the user requests.165- **Don't store images outside `screenshots/`.** Skills downstream expect them there.166- **Don't process images larger than ~10 MB without warning the user** — k-means on a 4K image is slow.167- **Per la lingua delle prose**: la skill scrive le sezioni in inglese di default. Se il `PROJECT.md` o l'input utente è in italiano, la skill rispetta la lingua dell'utente per la prosa (frontmatter resta in formato spec — nomi token in inglese).168169## Quality bar — what a good output looks like170171- **Palette section**: 8–15 named tokens with prose justification ("primary `#7839CD` reserved for the load-bearing CTA"). No "color1 / color2" placeholder names.172- **Typography section**: 6+ levels with samples that read as real product copy (extracted from PRD.md if available, or asked from the user). NEVER use `Lorem ipsum` or "Body 16/400/regular" as samples.173- **Confidence flags**: every section that contains a guess is marked. Future agents reading the DESIGN.md should know what to trust.174- **Screenshot citations**: the prose references `screenshots/<file>` for any inferred-from-image claim.175176A good DESIGN.md from this skill is one that the user can read, agree with, edit a few prose lines, and ship — not one they have to rewrite.