Content
# frontend-critic 🧐
[](https://opensource.org/licenses/MIT)
[](https://github.com/leonhoffmann86/frontend-critic/releases)
[](https://claude.ai/code)
A [Claude Code](https://claude.com/claude-code) subagent that judges rendered
pages in a real browser — and is not allowed to say "looks good" without a
screenshot to prove it.
## The problem
Coding agents routinely claim a page "looks right", "matches the site", or
"sits in the container" without ever rendering it. A syntactically clean
template in the database is not a rendered page. The result: confidently
reported layouts that are broken the moment a human opens them.
`frontend-critic` turns that claim into a verifiable check. It loads the page
via Playwright, compares it against a known-good reference page, checks
responsive breakpoints and the JS console, and reports **PASS/FAIL with
screenshot evidence** — separating what it *observed* from what it merely
*suspects*.
## How it works
```mermaid
graph LR
A["🎯 Target URL"] --> B["browser_navigate"]
B --> C["a11y snapshot<br/>(structure, cheap)"]
C --> D["screenshots<br/>(evidence)"]
D --> E["resize<br/>375 / 768 / 1440"]
E --> F["console check<br/>(JS errors)"]
F --> G{"reference page?"}
G -- yes --> H["load reference,<br/>same viewport,<br/>compare"]
G -- no --> I
H --> I["report:<br/>Observed / Suspected / Uncertain"]
I --> J{"PASS | FAIL"}
J -. "every claim carries<br/>a screenshot path" .-> I
```
Three iron rules drive every run:
1. **No verdict without a screenshot.** "Looks good" without a screenshot path
is forbidden.
2. **Compare against a reference.** Sibling page loaded at the same viewport;
differences named explicitly.
3. **Separate observation from suspicion.** Findings are reported as
`Observed` (with evidence), `Suspected` (indication, unverified), or
`Uncertain` — never collapsed into one.
## Installation
1. Add the Playwright MCP server to Claude Code (prerequisite):
```sh
claude mcp add playwright npx @playwright/mcp@latest
```
2. Copy the agent definition:
```sh
# globally, for all projects
cp frontend-critic.md ~/.claude/agents/
# or per project
cp frontend-critic.md your-project/.claude/agents/
```
> **Note on tool names:** The `tools:` list in the frontmatter uses the tool
> names as registered by `@playwright/mcp` (`mcp__playwright__browser_*`).
> If you registered the MCP server under a different name, adjust the
> prefixes accordingly — otherwise the agent falls back to inheriting all
> tools.
## Usage
Claude Code picks the agent up automatically for "does this page render
correctly?"-type tasks, or you can invoke it explicitly:
```
> Use the frontend-critic agent to check http://localhost:3000/pricing
against the reference page http://localhost:3000/about
```
## Example output
```
URL(s): http://localhost:3000/pricing
Reference: http://localhost:3000/about
Observed:
- [Container] Content breaks out of the site container, renders full-bleed
(evidence: ./screenshots/pricing-1440.png)
- [Footer] Site footer present and identical to reference
(evidence: ./screenshots/pricing-footer.png)
- [Console] 1 JS error: "Uncaught TypeError: prices is undefined"
Suspected:
- Missing page template assignment — reference page uses a boxed layout,
target does not.
Uncertain / not verifiable:
- Behavior behind the login (no credentials available).
Verdict: FAIL
```
## What it checks
- **Container/width** — content inside the site container, or full-bleed
breakout?
- **Site chrome** — header and footer present, no foreign/unstyled elements
injected.
- **Target element** — the expected form/button/link exists *and* is styled.
- **Console** — JavaScript errors.
- **Responsive** — 375 / 768 / 1440 px.
- **A11y quick pass** — field labels, button contrast.
## Related tools
Part of a small family of agency-ritual-named Claude Code tools:
- [team-sprint](https://github.com/leonhoffmann86/team-sprint) 🏃 — autonomous
plan → implement → review chain: every TODO item gets a full mini-sprint in
an isolated worktree, gated and fail-closed-reviewed, never auto-merged.
## Built by
**Leon Hoffmann** — [leonhoffmann.net](https://leonhoffmann.net) ·
[github.com/leonhoffmann86](https://github.com/leonhoffmann86)
## License
[MIT](LICENSE)