Skip to content
Back to skills

Design Audit

ASecurity

Visual audit of a web page at 7 screen widths (360–1920 px) — screenshots plus heuristics for horizontal scrolling, touch targets, visible focus, WCAG contrast, meta viewport, tiny text, missing alt/lang. Can inject a CSS file to preview a fix without touching production. Use for "check how the page looks on mobile", "design audit", "test responsiveness", "check contrast", "does the landing page work on a phone", and after any larger change to a page, widget or panel before reporting it works.

  • 4 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 15, 2026
ai-agentspythonbash

Works with

  • cli

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 3 files and shows the line behind each finding

Scanned October 15, 2026

npx -y skills add KamilMatysikAI/claude-agent-os --skill design-audit --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Design Audit?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Design Audit
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/kamilmatysikai-design-audit/badge)](https://www.skillsdirectory.com/skills/kamilmatysikai-design-audit)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: design-audit
description: Visual audit of a web page at 7 screen widths (360–1920 px) — screenshots plus heuristics for horizontal scrolling, touch targets, visible focus, WCAG contrast, meta viewport, tiny text, missing alt/lang. Can inject a CSS file to preview a fix without touching production. Use for "check how the page looks on mobile", "design audit", "test responsiveness", "check contrast", "does the landing page work on a phone", and after any larger change to a page, widget or panel before reporting it works.
argument-hint: "<url> [--breakpoints 360,768] [--css-file fix.css]"
allowed-tools: ["Read", "Bash", "Glob"]
---

# /design-audit — verify the page in the render, not in the code

Implements optional rule W1 (`.claude/rules-optional/web.md`). Code can look right while the page looks wrong. What counts is what a visitor sees, on a phone too. One command gives a full set of screenshots and a list of concrete fixes.

## Run

```
python .claude/skills/design-audit/scripts/design_audit.py <url> [options]
```

Examples:

```
# full audit, 7 widths, full-page screenshots
python .claude/skills/design-audit/scripts/design_audit.py https://example.com/landing --slug landing

# quick mobile check, first screen only
python .claude/skills/design-audit/scripts/design_audit.py https://example.com --breakpoints 360,768 --viewport-only

# preview a CSS fix on the live page without deploying it
python .claude/skills/design-audit/scripts/design_audit.py https://example.com --css-file fix.css
```

**One URL per call.** For several pages, loop over them one call at a time; a single long run is harder to diagnose when it hangs.

### Options

| Flag | Meaning |
|---|---|
| `--out DIR` | output directory (default `notes/design-audit/YYYY-MM-DD/` in the workspace) |
| `--slug NAME` | file name stem (default from the URL) |
| `--breakpoints 360,768,1280` | custom widths (default 360/480/768/1024/1280/1600/1920) |
| `--wait 1200` | extra ms after load (animations, late JS) |
| `--viewport-only` | screenshot only the first screen |
| `--headed` | show the browser window |
| `--storage-state FILE` | Playwright storage-state JSON with cookies, for pages behind a login |
| `--css-file FILE` | inject CSS before measuring: a measured preview of a fix, production untouched |
| `--no-consent` | do not click consent banners (by default the audit accepts them and measures the page behind) |
| `--no-focus` / `--no-contrast` / `--no-touch` | switch off one heuristic |
| `--static` | force the static HTML check |
| `--timeout 300` | seconds per URL |

## Requirements and graceful degradation

The full audit needs **Playwright for Python** (optional, not installed with the workspace):

```
pip install playwright
python -m playwright install chromium
```

Install it into the same Python environment the workspace uses. Without it, or when the browser cannot start, the script falls back to a **static check** of the raw HTML (HTTP status, meta viewport, blocked zoom, `lang`, images without `alt`, inline CSS that kills the focus outline). The report then starts with a "STATIC MODE" note and the script exits with code **3**. Tell the owner the result is partial and give the install command; never present a static result as a full audit.

If Bash is refused or unavailable (the queue's `safe` profile has no Bash), you cannot run the audit: block the task with a human task "run the design audit" or ask the owner to run the command, and say so in the report.

## Output

In the output directory:
- `report-HHMMSS.md` — findings grouped Critical / Should fix / Minor, each with selector, element text and the widths where it occurs;
- `findings-HHMMSS.json` — the same, machine-readable (compare before/after a fix);
- `screenshots/HHMMSS/<slug>-<width>.png` — the screenshots.

Nothing is overwritten; every run has its own timestamp.

## Heuristics

| Rule | What it detects | Severity |
|---|---|---|
| `overflow-x` | document wider than the window, plus the outermost elements sticking out | Critical |
| `touch-target` | buttons/fields under 44×44 px at widths ≤ 1024 px; under 24×24 px is a hard WCAG 2.2 failure | Critical / Should fix |
| `touch-target-inline` | bare text link with a small height on a phone | Minor |
| `focus-outline-removed` | CSS rules with `:focus { outline: none }` and no replacement (shadow, border, background) | Critical |
| `focus-invisible` | element whose styles do not change on `focus()` — confirm on the screenshot | Should fix |
| `contrast` | text contrast under 4.5:1 (large text 3:1), with real alpha compositing | Critical / Should fix |
| `viewport-meta` / `viewport-zoom-blocked` | missing meta viewport, or zoom blocked | Critical / Should fix |
| `tiny-font`, `img-alt`, `html-lang` | text under 12 px, images without `alt`, no `lang` | Minor |

## Read before reporting a result

- **HTTP ≥ 400 is reported as an error.** An audit of a 404 page looks like a normal audit. Check the report header first.
- **No results is a tool failure, not a clean page.** The report says so explicitly.
- **Contrast is only measured on solid backgrounds.** Gradient or image behind text = no result (fewer false alarms); look at the screenshot.
- **Shadow DOM and iframes are out of reach.** Audit an embedded widget at its own URL.
- **A black rectangle where an embedded video should be in a full-page screenshot is a rendering artefact**: browsers do not paint cross-origin frames that were never in view. Scroll to it and check before reporting "the video is broken".
- **`focus-invisible` is a signal, not a verdict.** Programmatic `focus()` does not always trigger `:focus-visible`. Confirm on the screenshot.
- **Touch targets are checked only up to 1024 px.** A 24 px link on a desktop with a mouse is not a defect.
- **Consent banners** are accepted automatically for common consent managers and common button texts in several languages; a large fixed overlay that remains is noted in the report.
- The script deletes nothing.

## When the page belongs to someone else

Auditing is read-only and always allowed. A fix for a site maintained outside this workspace is prepared as a CSS file plus a description, measured with `--css-file`, and handed to the owner for approval. It is never deployed from here (rule 15).

Files in this skill

  • SKILL.md6.2 KB
  • scripts/design_audit.py21.3 KB
  • scripts/probe.js14 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.