Skip to content
AI & Agents
Skill

/diff

Reconcile a converted/built web page against its source prototype with two complementary probes — a PIXEL/layout diff (stretched images, dropped wraps, blank renders, colour flips) and a STRUCTURAL content+typography diff (dropped/mis-slotted headings, eyebrows, CTAs;

BOOST
From plugin
adobe-skills
189155 skills4 MCP
Install
$ npx -y skills add adobe/skills --skill diff --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/diff

Context preview

The summary Claude sees to decide when to auto-load this skill.

Reconcile a converted/built web page against its source prototype with two complementary probes — a PIXEL/layout diff (stretched images, dropped wraps, blank renders, colour flips) and a STRUCTURAL content+typography diff (dropped/mis-slotted headings, eyebrows, CTAs;

SKILL.md

diff.SKILL.md
name: diff
description: Reconcile a converted/built web page against its source prototype with two complementary probes — a PIXEL/layout diff (stretched images, dropped wraps, blank renders, colour flips) and a STRUCTURAL content+typography diff (dropped/mis-slotted headings, eyebrows, CTAs; rendered-face font forks). Stack-agnostic via profiles (eds | generic). Use after converting a prototype to EDS/AEM (the stardust `deploy` skill Step 10), or for any prototype↔build fidelity check; invocable as the stardust `diff` skill and from workflows.
license: Apache-2.0
compatibility: Requires Node 22+, Playwright with Chromium resolvable from the project, playwright-cli on PATH, and the impeccable skill (github.com/pbakaus/impeccable) installed alongside stardust.

stardust:diff — prototype ↔ build reconcile

Two probes that compare a **source** prototype against a **built** page. They catch **disjoint** failure classes — run BOTH; either alone gives a false "looks fine".

Both are framework-agnostic Playwright probes that compare two rendered URLs by **computed style + DOM** (not pixels). All stack-specific language lives in a **profile** (`--profile eds|generic`); the comparison logic is generic.

When to use

  • After converting a prototype to EDS (the stardust `deploy` skill's Step 10) — use `--profile eds`.
  • Any "does the build match the design?" check between two rendered URLs (a Figma export vs a React build, a legacy page vs a rebuild) — use `--profile generic`.
  • Inside a conversion/QA workflow as the validation gate (see *Workflow use*).

Not for: a single static file with no JS decoration (use the build/harness URL so components are decorated — a raw `.plain.html` has no roles to classify).

The two probes

| Probe | Script | Sees | Blind to | |---|---|---|---| | **Pixel / layout** | `skills/diff/scripts/visual-diff.mjs` | stretched images, dropped max-width wraps, blank renders, surface/ground colour flips, image-count gaps | "right text, wrong slot"; a dropped CTA (full pixels, plausible colours → no flag) | | **Structural content + type** | `skills/diff/scripts/content-diff.mjs` | MISSING / ROLE-SWAPPED headings·eyebrows·CTAs, invented/dropped body copy, rendered-FACE font forks (width probe); dropped `placeholder`/`aria-label`/`title` values, missing/wrong/moved icons — on the main root AND the `header`/`footer` chrome roots by default | geometry / layout regressions |

`content-diff` extracts an ordered, role-classified inventory (`heading` / `eyebrow` / `cta`+href / `body`) from each root — the `--main` root(s) plus, by default, the `header` and `footer` chrome roots — classifying by **computed style + tag** so the prototype's DOM and the built DOM compare symmetrically, then diffs them root by root; a second inventory per root carries the `placeholder` / `aria-label` / `title` values and the icons.

Run it

# Prereq 0: playwright importable from the project root — probe
#   node -e "import('playwright').then(()=>process.exit(0))"
# and on failure install it AS A devDependency (npm i -D playwright pixelmatch pngjs cheerio
# --legacy-peer-deps — never --no-save: a --no-save install is PRUNED by the next real npm i,
# recorded twice in one run; extract SKILL.md § Setup). Run the copied scripts from the project
# root, not the plugin: ESM resolves `playwright` from the script's own location.
# Copy the WHOLE skills/diff/scripts/ dir: content-diff imports its local diff-profiles.mjs
# AND content-inventory.mjs. (The deploy gates #93/#94 now use their OWN synced copies in
# skills/deploy/scripts/ — A6/A2 are independent of this skill; the two copies must stay in
# sync until the diff-skill abrasion PR consolidates them.)
# Prereq: a RENDERABLE source. Static → serve from its own dir (python3 -m http.server).
# The build URL must be the DECORATED page (live/preview or a local harness), not raw markup.
# ONE server, ONE port — probe before starting one (curl is always present, lsof is not):
curl -sI localhost:8791/ | head -1                   # 200/404 = something serves the port; no line = free
curl -sI localhost:8791/<prototype>.html | head -1   # 200 = it serves YOUR dir: reuse it
command -v lsof >/dev/null && lsof -nP -iTCP:8791 -sTCP:LISTEN   # optional: names the pid
# Nothing answered → start yours. Answers but not your file → a foreign server: never kill
# a listener you did not start; prefer a per-project port — a stale server from another
# project makes both probes measure a foreign page. `lsof … || echo free` is not a probe —
# without lsof it prints "free" beside a live listener (recorded: a second server on the
# same port died at once and the round chased 404s).
PROTO="http://localhost:8791/<prototype>.html"
BUILD="https://<branch>--<repo>--<owner>.aem.page/<path>"   # or http://localhost:3000/<harness>

# 1. PIXEL/layout
node skills/diff/scripts/visual-diff.mjs   "$PROTO" "$BUILD" --profile eds --sections ".hero"

# 2. STRUCTURAL content + type
node skills/diff/scripts/content-diff.mjs  "$PROTO" "$BUILD" --profile eds   # --json dumps both inventories

Flags (both tools): `--profile eds|generic` (default `eds`), `--width <px>` (default 1280), `--main <selector[,selector…]>` (content root; content-diff defaults from the profile and takes a comma-separated list — every root is inventoried and diffed on its own and each finding line carries its root as `[root]`; visual-diff takes one selector, default `main`), content-diff only: `--chrome` / `--no-chrome` (default on — the `header` and `footer` roots, resolved as the first `<header>`/`[role=banner]` and `<footer>`/`[role=contentinfo]` outside the main root(s), are compared beside it; a side lacking one is measured as empty there and the root line says so), plus the live-target set (shared engine: `scripts/live-session.mjs` — every context sends the real-Chrome UA **and** the standard Chrome request headers; the UA alone still 403s on Akamai-class bot management):

  • `--ua <string>` — user a
Read more
Ships withadobe-skills

Repository of Adobe skills for AI coding agents.

Get the whole plugin

Other skills on adobe-skills.