Home / All Skills / Design & Motion / frontend-visual-qa
Design & Motion · daymade/claude-code-skills

frontend-visual-qa

Audits already-rendered web, landing-page, HTML deck/slide, browser tool/game, dashboard/admin, design-system, and desktop UIs using real-browser or native-app journeys, inspected screenshots, DOM geometry, responsive or projection viewports, and a bundled Playwright sweep. Use after UI implementation to find typography, wrapping, overlap, overflow, responsive, route, overlay, map, transient-state, data-visualization, browser-output, file-dialog, PDF/print, or Electron-shell defects, or to compare a rendered artifact with a visual reference. Do not use for greenfield UI design, extracting a design system from screenshots, general QA-program setup, or nonvisual code debugging.

L5 Restricted · Isolated sandbox & strict auditV2 Human-AuditedCredential / SessionExecute CommandNetwork AccessWrite FileDual-pass Audit
Author daymadeGitHub daymade/claude-code-skills ↗Stars 1385License MIT(仓库根 LICENSE 文件;GitHub API spdx MIT;Copyright (c) 2025 daymade)Commit d5c4678cb5
Control levels describe skill capabilities and suggested control measures; they do not represent quality or safety certifications, nor do they dictate usability. Usage decisions rest entirely with users and administrators. Different agent hosts apply varying constraints; do not assume hosts provide automatic protection. Third-party skill copyrights belong to their original authors. Use at your own risk.

1How It Works & Mechanism

The entire skill is structured around a "Rendered Evidence Tier System": Level A = real visible browser or native window driven journeys, Level B = isomorphic DevTools or project-native E2E, Level C = fresh headless automated sweeps via bundled scripts, Level D = source code, linter, build logs, and unit tests. Explicitly, lower-tier evidence must not be promoted into stronger conclusions. The bundled Playwright sweep is explicitly positioned as Level C, not a final verdict.

frontend-visual-qa/SKILL.md
| C | Fresh headless mechanical sweep from the bundled script | Overflow, wrapping, images, basic layout heuristics, screenshot candidates |
Immediately following this is the rule 'Do not promote a lower level into a stronger conclusion:' along with six prohibited promotion examples (e.g., unopened screenshot paths provide zero visual evidence, headless blank states cannot verify populated user states, a renderer URL cannot verify the Electron shell, handler invocation cannot verify Chrome print previews, pointer/hover styling cannot prove click efficacy). This turns "what counts as inspected" into deterministic rules rather than relying on agent self-reporting.

The bundled scripts intentionally carry zero npm dependencies: Playwright is resolved from the **audited project's** node_modules using createRequire(audited-project/package.json) first, falling back to the skill's own directory. If Playwright is missing from the project, it does not install it; instead, it degrades gracefully and truthfully reports its absence.

frontend-visual-qa/scripts/visual_layout_audit.mjs
createRequire(`${process.cwd()}/package.json`), // the audited project
Header comments explicitly detail cross-installation layout pitfalls: in pnpm workspaces, playwright-core is a non-hoisted transitive dependency of @playwright/test and absent from top-level node_modules, making the resolution fallback order playwright-core / playwright / @playwright/test. When unresolvable, the thrown error explicitly states: 'Do not change the audited project's dependencies unless that mutation is explicitly authorized.'—zero dependencies is an intentional design choice, not an oversight. The probe script follows the same strategy (checks <project>/node_modules/playwright/index.js first, falls back to import('playwright'), and on failure exits with code 2 while signaling that the probe can be skipped).

The scan is not static analysis: the entire auditPage detection routine is injected and executed inside a real Chromium page via page.evaluate, measuring metrics via getBoundingClientRect, scrollWidth-clientWidth, getComputedStyle, and checkVisibility directly on the real layout engine before returning structured issues.

frontend-visual-qa/scripts/visual_layout_audit.mjs
const result = await page.evaluate(auditPage, {
The caller launches chromium.launch({headless:true}) (with executablePath resolved across Chrome/Chromium/Edge paths via findChrome(), overridable by CHROME_PATH), iterating through a default three-tier viewport matrix (desktop-wide 1700x1000, desktop 1440x900, mobile 390x844 + deviceScaleFactor 2 + isMobile + hasTouch) via newPage -> goto -> screenshot -> evaluate. The answer to "why this works" is that defect determination is delegated to the browser's actual layout engine rather than guessing from parsed HTML.

"Whether text is actually rendered" is evaluated character by character: visibleTextFromNode uses a Range to measure individual character bounding boxes, progressively subtracting ancestor clipping rectangles (overflow:hidden/clip); clipped characters are replaced with whitespace. Thus, --forbid and --require check truly visible text, not raw textContent.

frontend-visual-qa/scripts/visual_layout_audit.mjs
range.setStart(node, index);
The accompanying rectSurvivesClips and collectNonScrollableAncestorClips compute geometric rectangle intersections. isVisible prioritizes el.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true }), falling back to display/visibility/opacity checks when unsupported. This is the critical differentiator from simple "DOM text reading" checks.

Overflow and clipping are calculated numerically rather than flagged as "suspicious elements": element-level overflowX is computed as el.scrollWidth - el.clientWidth, page-level as documentElement.scrollWidth - clientWidth, and section-level tracks both scrollWidth-clientWidth and rect.width - documentElement.clientWidth. Entries with explicit pixel values are emitted only when thresholds are exceeded.

frontend-visual-qa/scripts/visual_layout_audit.mjs
const overflowX = el.scrollWidth - el.clientWidth;
Defect categories include: page-horizontal-overflow (>1px, error), element-horizontal-overflow (>2px and overflowX!==visible, error), text-clipped (overflowY>2, overflowY is hidden/clip, and lacks line-clamp/ellipsis, error) versus text-truncated (has line-clamp/ellipsis, downgraded to warning), section-horizontal-overflow, and section-wider-than-viewport. Both thresholds and severities are explicit constants.

Media defects are segmented by granular lifecycle states rather than binary pass/fail: selected, rendered, notRendered, loaded, broken, stillLoading, deferredLazy, and missingSource. Offscreen, lazy-loaded, unrequested images are isolated as deferredLazy to avoid treating unrequested media as broken.

frontend-visual-qa/scripts/visual_layout_audit.mjs
const isDeferred = !mediaWalkRequested
The evaluation condition is !mediaWalkRequested && !inViewport && isLazy && (!img.complete || naturalWidth === 0 || !source). Passing --scroll-visible-media performs an initial pass over rendered media rows to warm up lazy loading; omitting this flag records deferred coverage instead of a defect. Additional checks include image-aspect-mismatch (object-fit is not cover/contain/scale-down and rendered aspect ratio deviates from natural ratio by >0.08, error) and image-heavy-crop (cover with ratio deviation >0.25, warning).

"Silent degradation" is detected via falsifiable empirical measurements rather than trusting API declarations: font mode renders a probe string containing Latin characters and measures width differences against an intentionally nonexistent fallback font family; document.fonts.check() is emitted only as a reference (as it returns true even when @font-face is completely absent).

frontend-visual-qa/scripts/silent_degradation_probe.mjs
const sentinel = measure('"NoSuchFamily__PROBE__"');
The probe string is 'Handgloves 0123456789 幅'. Header comments explain why Latin characters are required: CJK glyphs are full-width across fonts, meaning an all-CJK probe cannot detect font substitution. The measurement awaits document.fonts.load(...) and document.fonts.ready; otherwise, bundled fonts unused on the current page would look identical to unreleased fonts.

The font mode yields five mutually exclusive verdicts (platformGeneric, healthy, hostProvidedOnly, declaredButUnusable, absentStackEntries), classifying only hostProvidedOnly and broken asset as defects—conflating "bundled and functional" with "never shipped" causes users to mistakenly delete viable fallbacks.

frontend-visual-qa/scripts/silent_degradation_probe.mjs
const hostOnly = custom.filter((f) => f.actuallyRenders && !f.shippedByPage);
actuallyRenders is defined as |width - sentinelWidth| > 0.5; shippedByPage checks if a matching font face exists in document.fonts. Exit codes: 1 if hostOnly or brokenAsset triggers; 0 if neither is present.

Class mode detects unhandled silent degradations such as "entire CSS rule sets failing to match following major component library renames": referenced .ant-* class names are extracted from project CSS and checked against the installed library CSS; zero matches are flagged as dead.

frontend-visual-qa/scripts/silent_degradation_probe.mjs
Rules targeting them match nothing and fail silently — the component keeps the library's stock look.
Both CSS sets pass through stripCssComments (a character-by-character state machine respecting quotes and escape sequences), ensuring deprecated class names in comments do not trigger false positives, nor do commented class names trigger false negatives—as verified in tests/test_silent_degradation_probe.mjs test case 1. The script explicitly notes: if an alternative branch in a selector group still matches, the dead class incurs no penalty and requires manual confirmation before removal.

Evidence discipline is enforced in code, not just in prompt instructions: URLs in reports are strictly sanitized and redacted (retaining only origin + /<redacted-path> + query keys + #<redacted-fragment>), and target-related sensitive tokens are masked from rendered text. Headers can only be supplied via environment variables; passing --header directly is rejected before the browser launches.

frontend-visual-qa/scripts/silent_degradation_probe.mjs
process.stderr.write('--header is disabled; use --header-env for every header value\n');
visual_layout_audit.mjs incorporates redactUrlForEvidence, protectRenderedEvidence, and targetSensitiveTokens (which replace URL paths, query parameter values, and password fragments in page text with <redacted-target-value>). For targetEvidence, file: targets compute a contentSha256 hash, while web targets retain only targetStringSha256 fingerprints and query key names. Such default-closed evidence handling is rare among comparable skills.

2Core Capabilities

01Real-browser Level C automated sweep: Runs across a default three-tier viewport matrix (1700x1000 / 1440x900 / 390x844@DPR2+isMobile+hasTouch), capturing per-tier screenshots and outputting a JSON report, with exit codes 0/1/2 (clean / errors present or warnings under --fail-on-warning / invocation or runtime failure).
02Geometry and typography defect calculation: Emits page-, section-, and element-level horizontal overflows, distinguishes between text clipping and intentional truncation, detects orphaned heading lines, wrapped control elements, wrapped compact table headers, invalid CJK word-breaking boundaries, collisions between images and floating text, and card side-rail / inner-shadow AI artifacts (card-side-rail-ai-slop).
03Automated accessibility heuristics: Emits errors for visible interactive role elements that are non-focusable, visible interactive elements with aria-hidden, and focus rings eliminated via outline:none without :focus/:focus-visible replacements; emits warnings for missing focus rules entirely, and flags pages containing animations lacking a prefers-reduced-motion fallback.
04Mobile effective viewport verification: Emits errors when meta viewport is missing, when innerWidth or visualViewport.width deviates from requested width by over 24px, or when scale deviates from 1 by over 0.08, preventing "nominal mobile views that are actually scaled-down desktop layouts".
05Media state verification and lazy-load pre-warming: Granular eight-state classification, visits rendered media rows via --scroll-visible-media to trigger lazy loading, detects image aspect-ratio / object-fit / heavy-crop mismatches, and restricts scope via --media-selector.
06Page-type contract heuristics: Evaluates above-the-fold landing page headings and primary CTAs, dashboard task-surface presence, app/tool/game interactivity, deck slide structure and canvas size consistency, design-system six core signals, live-artifact framing and interaction density, as well as archetype drift and card density.
07Three silent-degradation probe modes: font (falsifies whether fonts truly render via sentinel width differences), class (checks whether class names referenced in project CSS are dead in installed library CSS), and shot (clips screenshots by element as embedded evidence, reporting dimensions in CSS px rather than device pixels).
08Attention inventory (attentionInventory): Tallies above-the-fold shallow visible text nodes, fully duplicated text clusters, and label echoes within the same container, explicitly outputting necessityVerdict: "not_evaluated"—ensuring overall text inspectability without certifying content necessity.

3External Dependencies

KindDependency / Endpoint
packagePlaywright(playwright-core / playwright / @playwright/test 三选一,从被审计项目解析)
cli本机 Chrome / Chromium / Edge 可执行文件(findChrome 的候选路径,可用 CHROME_PATH 覆盖)
network被审计目标 URL 及其子资源(唯一网络目的地,由调用者经 --url 指定)
cliNode.js 运行时与内置模块(node:crypto/fs/os/path/url/module);自带回归用 node --test

4Recommended Governance & Evidence

Suggested Controls for Safe Operation
For Agent Runtime
Isolated environment, per-use explicit authorization
For Administrators
Strict authorization, full audit, compliance signoff
Evidence & Triggers (File Paths & Excerpts)
  • 本地凭据 / 浏览器配置: Reads user login cookies/sessions/keychains: --storage <playwright-storage-state.json>: Reads Playwright login state files from disk (including cookies/
  • scripts/: Executes local scripts or commands: node scripts/visual_layout_audit.mjs (Main scanner: launches headless Chromium, injects auditPage
  • 网络端点: Declares external network access: page.goto(--url) (visual_layout_audit.mjs) and subsequent subresource requests initiated by the page itself—limited strictly to the audited target origin
  • 本地工作目录: File I/O and artifact outputs: <outDir>/<viewport>.png and <outDir>/frontend-visual-qa-report.json (containing issues,
Audit Notes: Adjudication basis (triggered conditions specified): The default execution path (supplying only a local URL) is low risk—local headless Chromium accesses the caller-specified target and writes to a temporary directory without external egress. However, the codebase contains four evaluable capabilities: ① Credentials can be read from environment variables and **actively dispatched to the target origin** (--header-env, with values excluded from argv); ② Reads Playwright login state files from disk (--storage, containing cookies/localStorage) to hydrate browser contexts; ③ Relies on the external third-party package Playwright (resolved from the audited project, not bundled with the skill); ④ Probe provides --ignore-https-errors to disable TLS verification for that context (SKILL.md documents that TLS is enabled by default, restricted to trusted self-signed origins, requiring explicit caller opt-in). Note: The scripts perform no file write mutations, operate in audit-only mode by default, and do not restart or redeploy the target; they do not access OS keychain, cookie databases, or .env files directly. Used strictly on local fixtures/local dev servers without credential flags, the effective attack surface is minimal.

5Second-Pass Verification

  • [ok] external_deps 逐条反查调用点是否真实存在 — grep 工具全量扫 scripts/:Playwright 候选数组(playwright-core / playwright / @playwright/test)、findChrome 的 process.env.CHROME_PATH、page.goto(url, { waitUntil, timeout: 30_000 })、SKILL.md 的 node --test 四处均逐字定位到文件行;网络 token 扫描只命中两处——probe 的 route.fetch({ headers: requestHeaders, maxRedirects: 0 }) 与 visual_layout_audit.mjs 用法字符串里的 http://localhost:port/ 示例,无第三方端点,无 axios / XMLHttpRequest / WebSocket / child_process / new Function。
  • [discrepancy] 安全结论反例搜索:是否存在未披露的外发/降级/隐藏脚本 — 主体结论(无第三方外发、无遥测、默认只读)成立,但发现两处 SKILL.md 未在安全语境点明的代码级能力:① probe 经 route.fetch 把 --header-env 提供的凭证以请求头形式发到目标 origin(值取自 process.env,不进 argv),文档只强调『argv 只含名字不含值』,未说『值会被转发给目标站』;② probe 有 --ignore-https-errors(ignoreHTTPSErrors: has('ignore-https-errors')),会关闭该上下文的 TLS 校验——SKILL.md 只在 sweep 段落自述『TLS stays enabled except for an explicitly trusted self-signed origin』,未提 probe 侧同一开关。两者都是显式 opt-in、需调用者自己写出 flag;未发现混淆内容、后门或隐藏脚本。
  • [ok] 凭证读取与文件写入面逐条复核 — credential_reads 三条、file_writes 三条均落到代码行:process.env[envName](probe)、storageState: flag('storage') || undefined、findChrome 的 CHROME_PATH/PROGRAMFILES/LOCALAPPDATA;写入侧为 outDir(默认 os.tmpdir()/frontend-visual-qa-<ISO>-<pid>)、frontend-visual-qa-report.json、截图 PNG。脚本不读 cookie 数据库、不读 keychain、不读 .env,也无删除行为。
  • [ok] 文件清单 glob 全量核对(含隐藏文件) — find -type f 得 24 个文件:SKILL.md 1 + scripts 3 + tests 2 + references 7 + evals/evals.json + evals/trigger-evals.json + evals/files 13(12 HTML + static-review.png);find -name ".*" 在 skill 目录内为空(无隐藏文件、无 .env、无嵌套仓库)。与 SKILL.md『Bundled Resources』清单一一对应,没有未列出的可执行文件。
  • [ok] 『实现原理』是否夸大:功能声明 vs 实际代码能力 — SKILL.md 称自带脚本为 'Playwright-powered mechanical viewport, layout, and media-state sweep with screenshots and JSON evidence',代码确为 chromium.launch + 三档视口 + 截图 + JSON 报告;report.checked 列的七项(navigation status and final URL、effective viewport and meta viewport、page and section overflow、rendered text wrapping and clipping candidates、custom interactive-role focusability candidates、rendered image request/load state and aspect candidates、page-type contract heuristics)在 auditPage 内逐条可定位到具体计算与 push。反向也不夸大:脚本在 report.notChecked 里主动列出做不到的项(真实浏览器 chrome 与打印预览、下载/剪贴板/弹窗/原生对话框、键盘旅程与焦点外观、完整 WCAG、GIS 交互、主观 parity),自述边界严于对外宣称。
  • [discrepancy] SKILL.md 关于『报告只写进唯一临时运行目录』的措辞与代码是否一致 — 默认路径确实唯一(os.tmpdir()/frontend-visual-qa-<ISO 时间戳>-<pid>,且拒绝非空 outDir 以防陈旧证据),但 --out 允许任意路径,脚本层不限制它落在被审计项目内;SKILL.md 的『Do not mutate the audited project merely to run the sweep』只是提示词层约束,代码不强制。属措辞与实现的轻微落差,非缺陷。
  • [ok] 注入面复核:被审计页面内容是否会进入可执行路径 — 四个注入浏览器的函数体全部来自 skill 自带文件(auditPage / collectAttentionInventory / primeVisibleMedia / collectScreenshotSections),页面内容只作为数据被 Range 测量、正则匹配、结构描述,不参与代码执行;无 eval、无 new Function、无 child_process,也没有把页面文本拼进 argv/shell 的路径(probe 的 --select 只交给 page.locator)。残余风险在模型侧(页面可埋针对审计 agent 的指令文本,本 skill 无过滤)与用户输入侧(--forbid/--require 正则无回溯上限)。
  • [ok] evals/ 的定位:是否确为自带评测夹具,能否在本地复跑出分数 — evals/evals.json 是 21 条 prompt + expectations 的行为回归集(12 条带 fixture 文件),evals/trigger-evals.json 是 24 条 should_trigger 路由集(14 true / 10 false),schema 与仓库内 daymade-skill/skill-creator/references/eval_pipeline_schemas.md 一致,且 skill-creator 的打包逻辑默认排除 root evals/(自述 'excluded by default as a development asset'),与 SKILL.md 的『excluded from packaged runtime content』吻合。但 skill 目录内没有 runner/评分器,仓库 .github/workflows/ci.yml 与 benchmark.yml 也未引用本 skill 的 tests 或 evals(grep 无命中),因此这些用例目前只在手动执行时生效。

6Verdict & Scenarios

  • Transforms "visual QA" from subjective prose into a verifiable evidence chain: defines falsifiable scope contracts upfront, gathers evidence according to A–D evidence tiers, and explicitly prohibits promoting weak evidence into strong conclusions (unopened screenshots, headless blank states, and renderer URLs are individually disqualified from supporting unverified assertions).
  • True mathematical computation over heuristic guesswork: computes overflow via scrollWidth-clientWidth pixel deltas, detects clipping by intersecting character-level Range bounds with ancestor clipping boxes, and evaluates images via rendered vs. natural aspect ratio deviations. Explicit thresholds, severities, --require/--forbid assertions, and exit codes 0/1/2 make it directly integrable into CI or agent loops.
  • Specialized in catching "all green gates with broken pixels" regressions: silent_degradation_probe's font mode falsifies real font rendering using sentinel width deltas (explicitly addressing false positives from document.fonts.check()), while class mode uncovers rules that never match after library renames, with only two of five states classified as defects to prevent deleting functional fallbacks.
  • Default read-only posture with granular permission boundaries: source fix, interaction, and target mutation permissions are decoupled and non-transitive. Scripts do not restart, redeploy, install dependencies, or mutate the audited project; evidence undergoes structured redaction before disk write (retaining only origin, path placeholders, query keys, and masked fragments).
  • Bundled test fixtures built with intentional negative samples: includes horizontal overflow pages, dead-click galleries, error bars that auto-dismiss in 700ms, and stale download/empty share links, formalizing "how to adjudicate quality gates" into 21 behavioral test cases and 24 route test cases rather than relying on abstract documentation.
  • Best for: Ideal for teams where the UI is already running and requires verified visual inspection: frontend or design-system maintainers conducting pre-merge rendered inspections; QA engineers seeking automated evidence for "build passes but page is broken" defects; and scenarios requiring real-path verification for browser outputs such as Electron/native windows, print/PDF views, download/share flows, maps, and HTML decks/slides. Also suited for using visual_layout_audit.mjs as a CI gate (against local dev servers or fixtures with exit codes) or integrating silent_degradation_probe's font/class modes into design-system regressions. Especially valuable for Chinese and East Asian UIs (evaluating CJK line-breaking boundaries and mixed CJK/Latin typography).
    Not for: Not intended for the requirements phase or greenfield UI design from scratch (description explicitly excludes greenfield UI design), extracting design systems backward from screenshots (reserved for design skills), orchestrating comprehensive QA programs and release gates (better handled by qa-expert), or non-visual code debugging (such as diagnosing React hydration errors). Furthermore, it does not provide full WCAG certification, subjective aesthetic judgments, GIS map interaction verification, or replace manual subjective visual alignment against reference designs; projects lacking Playwright must fall back to Level A/B, as the bundled scripts skip execution rather than installing dependencies.
    Install Agent-Ready
    ① Verified Mirror 2026-09-15
    Option A · Direct DownloadDownload frontend-visual-qa.tar.gz
    sha256: 48ff3a56b28549a2…
    Option B · Copy Guide for Agent
    install.json
    Agents automatically download and verify mirrors from this JSON guide.
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit d5c4678cb5.