May 8, 2026
Give Claude Code Eyes: Playwright for Live UI Observation
Claude Code writes frontend code without seeing the result. Playwright fixes that - and it changes how fast you can build.
When I started building a Next.js dashboard with Claude Code, I noticed something odd. The AI was writing clean, structured code. But neither of us could see what it actually looked like in a browser until I manually refreshed and checked. That lag - write, wait, check, write again - was friction I didn't need.
I added Playwright as a dev observation tool. Not for testing. Just to watch.
What "Observation Tool" Means
Most people hear Playwright and think test automation - test suites, assertions, CI pipelines. That's one use. But there's a simpler one: put a browser in front of the code and capture what you see.
With one command, I can take a full-page screenshot of the current state of the app. I can capture every console error and page crash as it happens. I can watch the browser navigate, pause, and interact - all from my terminal.
That's not testing. That's observation.
How I Set It Up
The setup on my actual project was straightforward:
- Install as a dev dependency in
frontend/- Playwright 1.59.1, Chromium only - A gitignored config file -
playwright.config.tswithbaseURL: http://localhost:3003andslowMo: 800so you can actually watch what's happening - A gitignored scripts folder - keeps the repo clean, scripts stay local
- A quick screenshot command - one command, full page, done
I also keep a global Playwright installation that works outside any specific project. One command to screenshot any URL or local HTML file. Fast enough to run mid-session without breaking flow.
One thing I learned from using it daily: page.locator('textarea') is more reliable than getByPlaceholder() with regex. The placeholder selector looked right but failed silently. Direct element locators don't.
What This Actually Changes
When Claude Code writes a UI component, I screenshot it immediately. If something looks wrong, I have a concrete image to work from - not a description, not a guess. The AI can reference that screenshot directly and respond to something real, not something imagined.
Console logs matter too. Capturing every console.error and pageerror the moment they appear means I catch issues before they compound - not minutes later when I happen to open the browser manually.
Think of it like a camera on a production line. Quality control doesn't happen by reading the assembly manual. You watch the output.
Why This Matters Now
Anthropic just doubled Claude Code rate limits across all plans and removed peak-hour throttling. Longer uninterrupted sessions. More code being written per run, with fewer breaks.
The more Claude Code writes per session, the more important it is to have a way to observe the result without stopping to check manually. Playwright fits into that loop without adding ceremony.
Set it up once. Keep it gitignored. Use it every session.
Copy This to Your Agent
I use a Claude Code skill to wire this up in any project automatically. Save the content below as .claude/commands/playwright-setup.md in your project - then just tell Claude "/playwright-setup" and it handles the rest.
# Playwright Setup
Install and wire up Playwright as a live development observation tool in any frontend project. Claude uses it to open a browser, interact with the UI, capture screenshots, and read console logs - then reports back.
---
## Step 0: Discover Before Touching Anything
Before writing a single file, detect or ask:
1. **Frontend directory** - check if there's a `frontend/`, `client/`, `app/`, or if the root is the frontend. Ask if unclear.
2. **Package manager** - check for `pnpm-lock.yaml` → pnpm, `yarn.lock` → yarn, `package-lock.json` → npm. Default: pnpm.
3. **Dev server port** - check `.env.local`, `.env`, then `package.json` dev script for `--port`. NEVER assume 3000.
4. **TypeScript** - check for `tsconfig.json`. If present: `.ts` files. If not: `.js` files.
---
## Step 1: Install
Run inside the frontend directory:
```bash
{packageManager} add -D @playwright/test
npx playwright install chromium
```
Chromium only - smallest footprint.
---
## Step 2: Scaffold `playwright.config.ts`
Create `{frontendDir}/playwright.config.ts` (gitignored):
```ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './playwright-scripts',
timeout: 30_000,
retries: 0,
reporter: 'list',
use: {
baseURL: 'http://localhost:{PORT}',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
outputDir: 'test-results',
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'], launchOptions: { slowMo: 800 } },
},
],
});
```
Replace `{PORT}` with your dev server port. `slowMo: 800` goes in `launchOptions`.
---
## Step 3: Add package.json Scripts
```json
"pw": "playwright test",
"pw:ui": "playwright test --ui",
"pw:screenshot": "playwright test playwright-scripts/screenshot.spec.ts"
```
---
## Step 4: Gitignore All Playwright Files
Append to `{frontendDir}/.gitignore`:
```
# Playwright
playwright-report/
test-results/
screenshots/
playwright-scripts/
playwright.config.ts
```
---
## Step 5: Verify
```bash
cd {frontendDir}
{packageManager} run pw:screenshot
```
Expected: `screenshots/home.png` created, test passes.
---
## Critical Selector Rules
- Use `page.locator('textarea')` not `page.getByPlaceholder()` - placeholder regex fails silently
- Prefer `page.locator('[data-testid="..."]')` when test IDs exist
- For AI/async responses: `page.waitForFunction()` on DOM state - more reliable than spinners
- Always set `test.setTimeout(120_000)` for tests that wait on AI responses
## Console Capture (add to every script)
```ts
const logs: string[] = [];
page.on('console', msg => logs.push(`[${msg.type()}] ${msg.text()}`));
page.on('pageerror', err => logs.push(`[pageerror] ${err.message}`));
```