Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx skills add pedroiff0/awesome-skills --skill frontend-visual-verificationgit clone --depth 1 https://github.com/pedroiff0/awesome-skillsWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/pedroiff0/awesome-skills/frontend-visual-verification)<a href="https://agentmods.dev/skills/pedroiff0/awesome-skills/frontend-visual-verification"><img src="https://agentmods.dev/badge/skills/pedroiff0/awesome-skills/frontend-visual-verification/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/pedroiff0/awesome-skills/frontend-visual-verification"><img src="https://agentmods.dev/badge/skills/pedroiff0/awesome-skills/frontend-visual-verification.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00066 | $0.04592 |
| Opus 5 | $0.00033 | $0.02296 |
| Sonnet 5 | $0.00013 | $0.00918 |
| Haiku 4.5 | $0.00007 | $0.00459 |
Grade B, and why
frontend-visual-verification scanned grade B with 2 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 6d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Sends data to an external URLmediumData exfiltration
A POST to an outside endpoint may be telemetry or may be exfiltration; either way the mod talks to somewhere, and you should know where.
- **Demo visual change invisible until you rebuild BOTH `app` and `app-demo`, AND the browser loads `/css/main.css` from the PRINCIPAL, not the demo.** In the financas-app setup the page `/demo/app` references the styles Makes network callslowCapability
Not a fault in itself. Listed so you know the mod talks to something, and to what.
`curl -s http://HOST/css/main.css | grep -c 'your-new-token'` How it starts
The opening of the file, as written. The whole thing — 232 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Frontend Visual Verification (beating stale browser cache)
Overview
You changed a stylesheet/template and want to see it worked. The trap: a
browser_vision screenshot can show the old layout even though the server
is already serving your new code. The browser cache (notably for /css/*.css
and other static assets) survives a container rebuild and a re-navigate to the
same URL — the HTML re-renders but the stale stylesheet is reused. The vision
model then confidently describes the OLD layout as if it were real.
Never trust a single screenshot when it contradicts the DOM or the served asset. Cross-check with the triple below.
The triple-check (do this before declaring "it didn't work")
- DOM —
browser_snapshot(). The markup reflects the HTML you served. If your new wrapper/selector is present, the HTML is new. - Computed style — run in
browser_console, read the returned dict:
If this shows OLD values while the DOM shows the new structure, it's cache.(() => { const el = document.querySelector('.your-new-selector'); if (!el) return 'SELECTOR NOT IN DOM'; const cs = getComputedStyle(el); return { display: cs.display, position: cs.position, grid: cs.gridTemplateColumns, borderRight: cs.borderRightWidth }; })() - Served asset — from the terminal:
curl -s http://HOST/css/main.css | grep -c 'your-new-token'Server new + browser computed-style old ⇒ 100% cache, not your code.
Force a fresh stylesheet (no hard-reload in the toolset)
Bust the cache by rewriting the <link> href to a unique query string, wait
~600ms, then re-screenshot:
(() => {
const l = document.querySelector('link[rel="stylesheet"]');
l.href = l.href.split('?')[0] + '?cb=' + Date.now();
return 'busted: ' + l.href;
})()
Now browser_vision reflects the new CSS.
Container / static-asset gotchas
- Docker with read-only filesystem: local file edits do NOT reach the
running container. Rebuild/restart first:
docker compose -f <file> -p <proj> up -d --buildRepoHANDOFF.md/AGENTS.mdusually state this — read them before debugging "why isn't my change showing up". - Autologin demos / protected pages: a nav-guard may bounce you to
/loginor the landing. To reach a protected page in the browser, either hit the auth route that sets the cookie (e.g.POST /api/auth/loginvia curl to grab a cookie jar, then reuse withcurl -b jar), or just fill the login form in the browser with demo credentials. Don't debug layout while stuck in a redirect loop. - CSS
<link>without?v== rebuild never reaches the browser (real session, ~20 wasted iterations). If the header serves<link rel=stylesheet href="/css/main.css">with NO query string, the browser caches the file in disk and NO container rebuild updates it — the DOM keeps measuring the old rule (e.g.align-items: stretch) even though the host file already saysstart. Fix: version the link like the footer already does —href="/css/main.css?v=<%= assetVersion %>"(theassetVersionis set inapp.localsby the server; in an EJS partial use the bare global<%= assetVersion %>, NOTapp.locals.assetVersion— that throws a runtime 500). Then changing CSS and bumpingASSET_VERSIONactually busts the cache. - Demo visual change invisible until you rebuild BOTH
appandapp-demo. The browser requests/css/main.css(absolute, no/demo/), and nginx routes/css/*→location /→ the app principal, NOT app-demo. So a CSS/header- Demo visual change invisible until you rebuild BOTH
appandapp-demo, AND the browser loads/css/main.cssfrom the PRINCIPAL, not the demo. In the financas-app setup the page/demo/appreferences the stylesheet at/css/main.css(absolute, no/demo/prefix); nginx routes/css/*→location /→ the app principal container, NOTapp-demo. So even after you rebuildapp-demo, the browser keeps showing the OLD CSS because the principal is still serving the previous file. Symptom that cost a full debug cycle: DevToolsdocument.styleSheetslistedhttp://HOST/css/main.css(no/demo), and a computed-style check reported the OLDmarginTopeven thoughcurl /demo/css/main.cssclearly had the new rule — the two URLs are DIFFERENT files. Fix: rebuild BOTH containers (docker compose up -d --build app app-demo) and verify the served bytes of the PRINCIPAL:curl -s http://HOST/css/main.css?v=probe | grep -n 'your-new-token'. If it still shows the old rule,app(principal) wasn't rebuilt — rebuilding onlyapp-demois not enough. - ASSET_VERSION cache-bust is mandatory for the USER's browser, not just yours.
header.ejsalready links/css/main.css?v=<%= assetVersion %>andfooter.ejsversions the JS the same way (app.locals.assetVersion = process.env.ASSET_VERSION || '1'). When you ship a CSS fix, bumpASSET_VERSIONin the compose env (ASSET_VERSION: ${ASSET_VERSION:-1}→ passASSET_VERSION=2 docker compose up -d --build app app-demo) so the user's already-open tab actually re-fetches the new asset instead of using the cached?v=1. For YOUR OWN validation you can also just navigate the browser directly to the versioned URL (/css/main.css?v=2) to force a fresh fetch before measuring computed style. /css/main.css(principal) and/demo/css/main.css(app-demo) are DIFFERENT files — grep the one the browser actually loads. In financas-app the page/demo/apprequests the stylesheet at the absolute/css/main.css(no/demo/), so nginx routes it tolocation /→ the app principal container. Thecurl /demo/css/main.cssyou may be checking is the demo's copy and can have your new rule while the browser still shows the old one. Always cross-check the SAME url the browser fetches:curl -s http://HOST/css/main.css | grep -c 'your-new-token'. If that shows 0 but/demo/css/main.cssshows 2, the principal wasn't rebuilt —docker compose up -d --build app app-demo(both), then re-grep/css/main.css.- Nested-card spacing pattern (financas-app dashboard). Cards that are children of
.container/<main>but whose preceding sibling is a<div class="grid-2">(not a.card) are NOT reached by the global.card + .card { margin-top }, so they "colam" no módulo anterior. Fix:.container > .card { margin-top: 1.5rem }+.container > .card:first-child { margin-top: 0 }. Cards nested inside another card (e.g. "Custo mensal" inside the Veículos card) also miss.card + .card→ add.card > .card { margin-top: 1.25rem }. And restoremargin-topinside@media (max-width: 820px)for.grid-2 > .card + .card/.split > .card + .cardso stacked columns keep their gap. - Rosca (donut) chart labels. In financas-app the SVG donut is built in
app/public/js/financas-lib.js(funçãorosca). It drew a fixed, oversized<text>percent label inside each slice — Pedro called this "feio" / "percentuais muito grandes". Fix: drop the fixed<text>, keep the native<title>(hover showslabel — % (R$ valor)), and rely on the legend<ul>below the chart (already renders label + % + value). Verify by snapshot: center of donut should be empty (or show only the total), legend below carries the %s.
- Demo visual change invisible until you rebuild BOTH
What ships with it
2 files beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 6d ago First seen · 232 lines · 66 tokens per session scan B 8ce3b6f83f62
frontend-visual-verification is a skill published in the GitHub repository pedroiff0/awesome-skills (1 stars, last pushed 2d ago), licensed MIT. It adds 66 tokens to every session and 4,592 once invoked, about $0.0003 per session on Opus 5. A static security scan graded it B with 2 findings (sends data to an external url, makes network calls). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-09-03.
Other skills, from other repositories
inspecting-hermes-desktop-dom
When you are developing apps/desktop and the user is running that same app (hgui / npm run dev), you can read the live rendered DOM of the window they are looking at — computed styles, geometry, which CSS rule actually won, console output — instead of inferring it from .tsx and being wrong.
fixing-motion-performance
Audit and fix animation performance issues including layout thrashing, compositor properties, scroll-linked motion, and blur effects. Use when animations stutter, transitions jank, or reviewing CSS/JS animation performance.
cross-browser-typography-qa
Use this skill when web text looks clipped, flattened, wrapped incorrectly, misaligned, or materially different between Chromium and WebKit/Safari. Treat text rendering as both a geometry problem and a visual paint problem: passing DOM bounds does not prove that every glyph is intact.
ui-debug-workflow
Debug UI changes with a repeatable evidence-first workflow. Use when validating visual regressions, reproducing frontend bugs, comparing baseline vs changed behavior, collecting screenshots/DOM/logs, or producing stakeholder-ready UI debug reports. Keywords: ui bug, visual regression, browser devtools, playwright…
inspecting-hermes-desktop-dom
Read the live Hermes desktop DOM/CSS over CDP.
implementation-debugging
Use when animation doesn't work as expected, has bugs, or behaves inconsistently.