Skip to content
Back to skills

Browser Verification

ASecurity

Load BEFORE any check in a real browser — the Claude Code Browser pane, headless Chrome over CDP, headless Playwright, or the WebKit (WKWebView) probe. Lists the ways those instruments misreport (blank captures, swallowed Escape/Tab, no blur events, dead observers, throttled timers, no hyphenation, a Chromium-only engine, a CSSOM walk that finds nothing, mocks the service worker bypasses) with the probe or control that tells "the pane lied" from "the app is broken". Use when verifying a UI ch...

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 11, 2026
developmentjavascriptgojavashellnodeapi

Works with

  • claude code
  • cli
  • api

Security analysis

A100/100

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

Scanned November 11, 2026

npx -y skills add ChulioZ/spielwirbel --skill browser-verification --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Browser Verification?

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

Security grade badge for Browser Verification
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/chulioz-browser-verification/badge)](https://www.skillsdirectory.com/skills/chulioz-browser-verification)

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: browser-verification
description: >-
  Load BEFORE any check in a real browser — the Claude Code Browser pane,
  headless Chrome over CDP, headless Playwright, or the WebKit (WKWebView)
  probe. Lists the ways those instruments misreport (blank captures, swallowed
  Escape/Tab, no blur events, dead observers, throttled timers, no hyphenation,
  a Chromium-only engine, a CSSOM walk that finds nothing, mocks the service
  worker bypasses) with the probe or control that tells "the pane lied" from
  "the app is broken". Use when verifying a UI change, running an
  accessibility/UI audit or a screen deep-dive, or reviewing a PR in a browser.
---

# Verifying in a browser without believing its lies

Every instrument this repo verifies UI with has failure modes that look
**exactly** like an app bug — and each one has cost at least one session a cycle
of "fixing" working code. The full write-ups live beside this file; this page is
the index you read first, so you know which one to open when a reading looks
wrong.

**The general rule:** before believing a negative result (nothing happened,
nothing rendered, nothing matched), run a **control whose answer you already
know** in the same call — an untouched element, a bare probe with no app code, or
the bug put back on purpose. If the control misreports too, it is the instrument.

Before you start, always:

- Launch `preview_start {name: "dev-temp-data"}` — never the production data
  (`.claude/rules/no-reading-production-data.md`).
- After a shell-asset edit, defeat the service worker **and** the HTTP cache
  (`.claude/rules/pwa-service-worker.md`, "Verifying a shell-asset change").
- Prefer text probes (`read_page`, `javascript_tool`) to screenshots; take one
  screenshot at the end, right after a fresh `navigate`.

## Symptom → reference

| You see | It is probably | Read |
|---|---|---|
| A blank or half-blank screenshot; scroll/input actions time out; an animating card captures as a hole; `ResizeObserver`/`IntersectionObserver` never fire; a runtime `data-scheme` flip leaves the paint stale; `innerWidth` 0 | the pane's paint/compositor and observer gaps — `resize_window` fixes the 0×0 viewport, nothing revives the observers | [preview-pane-paint-artifacts.md](preview-pane-paint-artifacts.md) |
| Escape (or Tab) does nothing; a focus trap looks broken | the pane did not deliver the key — run the capture-phase `keydown` spy, then dispatch the event | [escape-keypresses-never-reach-the-preview-pane.md](escape-keypresses-never-reach-the-preview-pane.md) |
| A commit-on-blur editor looks completely dead | `document.hasFocus()` is false, so `blur()` fires no event — dispatch `FocusEvent('blur')` in ONE call | [blur-events-never-fire-in-the-preview-pane.md](blur-events-never-fire-in-the-preview-pane.md) |
| A probe that sleeps with `setTimeout` hangs, then later probes see impossible state | the hidden pane throttles timers — wait on the condition via `MessageChannel`, re-`navigate` after a timeout | [hidden-pane-throttles-timers.md](hidden-pane-throttles-timers.md) |
| At a phone width the viewport reads wider than you set; a menu overflows after a resize | the mobile emulation widened to fit an overflow; `resize_window` fires no `resize` | [emulated-viewport-widens-on-overflow.md](emulated-viewport-widens-on-overflow.md) |
| `hyphens: auto` splits a word with no hyphen | the pane (and Playwright's Chromium) has no hyphenation dictionaries — judge in real Chrome or WebKit | [browser-pane-has-no-hyphenation.md](browser-pane-has-no-hyphenation.md) |
| A `document.styleSheets` walk finds zero matching rules | CSS nesting made every style rule a truthy `cssRules` container — recurse on `length` | [cssrules-walk-is-blind-under-nesting.md](cssrules-walk-is-blind-under-nesting.md) |
| A layout/canvas claim verified in the pane — multicol, fragmentation, recent CSS, canvas export | the pane is Chromium; half the traffic is WebKit — run the WKWebView probe, with a control, in both engines | [browser-pane-is-chromium-only.md](browser-pane-is-chromium-only.md) |
| An exported canvas shows as a broken image; `fetch(blobUrl)` fails | the app's CSP refuses `blob:` images and fetches (and a data-URL `<img>` failed too) — draw `createImageBitmap(blob)` onto a visible canvas | [canvas-export-previews-and-the-csp.md](canvas-export-previews-and-the-csp.md) |
| Playwright `route()` mocks are ignored | the service worker issued the request and the SWR cache painted first — `serviceWorkers: 'block'`, clear `swr` keys | [playwright-mocks-and-the-service-worker.md](playwright-mocks-and-the-service-worker.md) |

## When the pane is unusable: headless Chrome over CDP

If the pane goes hidden mid-run (no screenshots: "not compositing frames") or
its input wedges, drive a headless Chrome yourself. `scripts/cdp.js` exports
`connectCdp`, a dependency-free DevTools Protocol client (Node's global
`WebSocket`); `scripts/capture-landing-shots.js` is the worked caller, with
`evaluate` and `navigate` helpers.

- Set the viewport with `Emulation.setDeviceMetricsOverride` — never
  `chrome --screenshot --window-size`, which floors the CSS viewport at 500px
  (`.claude/rules/landing-product-screenshots.md` §1).
- Capture with `Page.captureScreenshot`; off macOS set `CHROME_BIN`.
- Run it against a **scratch** server (`DATA_DIR=$(mktemp -d)`, never the
  production `data/`) with `RATE_LIMIT_MAX` and `AUTH_RATE_LIMIT_MAX` raised
  (`docs/configuration.md`): ~135 navigations trip the default limiter, and the
  429s then read as app failures.
- To wear another design as a signed-in account, `PATCH` the account's
  `design` field (`accountApi('PATCH', '/me', { design })`) and re-navigate;
  `?design=` does not stick for a logged-in account.

Real headless Chrome hyphenates, unlike the pane and Playwright's bundled
Chromium; it is still Chromium, so it does not replace the WebKit probe.

## Adding to this skill

A new learning about how a browser *instrument* misreports goes here as its own
file, plus a row in the table above — not into `.claude/rules/`, where it would
load into every session including the ones that never open a browser (#1551).
A learning about the **app's** CSS or JS that happened to be found in a browser
is still a rule, scoped to the files it lives in.

Files in this skill

  • SKILL.md6.2 KB
  • blur-events-never-fire-in-the-preview-pane.md4 KB
  • browser-pane-has-no-hyphenation.md2.5 KB
  • browser-pane-is-chromium-only.md8.1 KB
  • canvas-export-previews-and-the-csp.md1.6 KB
  • cssrules-walk-is-blind-under-nesting.md4 KB
  • emulated-viewport-widens-on-overflow.md2.1 KB
  • escape-keypresses-never-reach-the-preview-pane.md6.1 KB
  • hidden-pane-throttles-timers.md1.9 KB
  • playwright-mocks-and-the-service-worker.md1.6 KB
  • preview-pane-paint-artifacts.md8.3 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.

View all in development →

Comments

Loading comments…

Newsletter

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