Skip to content
Agentmart
Submit a tool

the-controller-debugging-ui-with-playwright

Use when a UI behavior doesn't work as expected (key not responding, focus lost, mode not changing) and code reading alone isn't enough — runs Playwright in…

Skill by kwannoel

IndexedMIT★ 13
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/kwannoel-the-controller-debugging-ui-with-playwright

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Use when a UI behavior doesn't work as expected (key not responding, focus lost, mode not changing) and code reading alone isn't enough — runs Playwright in browser mode to reproduce, isolate, and pinpoint the root cause

Use cases: design, testing

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/the-controller-debugging-ui-with-playwright

What's inside

Skill name
the-controller-debugging-ui-with-playwright
Description
Use when a UI behavior doesn't work as expected (key not responding, focus lost, mode not changing) and code reading alone isn't enough — runs Playwright in browser mode to reproduce, isolate, and pinpoint the root cause
License
MIT
Instructions
183 lines in SKILL.md · view on GitHub

Agent Skills spec issues

  • body: contains an absolute path from the author's machine

Files (1)

  • SKILL.md

SKILL.md (first lines)

# Debugging UI/UX Issues with Playwright

## When to Use

A user reports a UI behavior that doesn't work as expected — a key doesn't respond, focus is lost, a mode doesn't change, a visual state is wrong — and reading the code doesn't make it obvious why.

**Don't skip to fixes.** Use the `the-controller-systematic-debugging` skill's iron law: no fixes without root cause investigation first. This skill is the browser-specific investigation technique.

## Setup Checklist

Before writing any test, verify all three servers:

```bash
# 1. Backend (port 3001)
lsof -i :3001 -P | grep LISTEN
# If not running:
cd src-tauri && cargo run --bin server --features server

# 2. Frontend dev server (port 1420)
lsof -i :1420 -P | grep LISTEN
# CRITICAL: verify it's serving the right directory
ps -p $(lsof -t -i :1420) -o command=
# If it says /Users/noel/projects/the-controller — that's the main repo
# Code changes MUST go to that directory, not a worktree

# 3. Playwright dependencies
npm install  # worktrees need their own node_modules
```

**Silent failure trap**: The axum server has a `fallback_handler` that returns `null` for any unregistered API route. If a feature silently does nothing in browser mode, check if the API endpoint exists in `src-tauri/src/bin/server.rs`.

## The Four Phases

### Phase 1: Reproduce

Write a Playwright test that does exactly what the user did. No cleverness — just automate the steps.

```typescript
test("reproduce: o key should enter insert mode", async ({ page }) => {
  await page.goto("/");
  // Navigate to the right state
  await page.keyboard.press("Space");
  await page.waitForTimeout(300);
  await page.keyboard.press("n");
  // ... exact steps the user took ...

  // Screenshot at each step
  await page.screenshot({ path: "e2e/results/step-01.png" });

  // Assert the expected outcome
  expect(content).toContain("typed text");
});
```

Run with:

```bash
# Default: headless (no focus stealing, same browser engine)
npx playwright test <file> --project=e2e --trace on

# Optional: headed (opens a visible browser window — steals focus on macOS)
npx playwright test <file> --project=e2e --headed
```

**Use headless by default.** It runs the exact same browser engine and rendering pipeline — no accuracy loss. Pass `--trace on` to get DOM snapshots, screenshots, network logs, and console output at every step, then review with `npx playwright show-trace <trace.zip>`.

Only use `--headed` when you need live visual interaction (e.g., pausing with `await page.pause()` to manually inspect state).

If the test passes, the bug isn't what you think. If it fails, you have a reproducible case.

### Phase 2: Isolate

Break the problem into smaller pieces to narrow the scope:

- **Specificity**: If `o` doesn't work, does `i` work? Does `a` work? Does ANY command of that type work?
- **Granularity**: If typing doesn't work, does one character work? Two? Use individual `page.keyboard.press()` calls with `waitForTimeout()` between them.
- **Mechanism**: Does `page.keyboard.type()` work? Does `page.keyboard.insertText()` work? Does `page.evaluate()` to directly call APIs work?

Check content after EACH individual action:

```typescript
await page.keyboard.press("o");
await page.waitForTimeout(300);
content = await getContent();
console.log("After o:", JSON.stringify(content));

await page.keyboard.press("h");
await page.waitForTimeout(200);
content = await getContent();
console.log("After o + h:", JSON.stringify(content));
```

### Phase 3: Instrument

Once you know the symptom (e.g., "second character isn't typed"), add diagnostics:

#### Focus tracking (most common root cause)

```typescript
// Install global focus monitor
await page.evaluate(() => {
  document.addEventListener("focusin", (e) => {
    console.log("[FOCUS] focusin:", (e.target as HTMLElement)?.tagName,
      (e.target as HTMLElement)?.className?.substring(0, 60));
  });
  document.addEventListener("focusout", (e) => {
    console.log("[FOCUS] focusout:", (e.target as HTMLElement)?.tagName,
      (e.target as HTMLElement)?.className?.substring(0, 60));
  });
  // Blur listener with stack trace — this is the money shot
  const target = document.querySelector('.cm-content');
  target?.addEventListener("blur", () => {
    console.log("[FOCUS] BLUR!", new Error().stack);
  });
});

// Check activeElement after each action
const checkFocus = async (label: string) => {
  const info = await page.evaluate(() => ({

From kwannoel/the-controller, MIT.

More from kwannoel/the-controller

Signals

Stars
13
Forks
2
Open issues
60
Last commit (this folder)
Mar 12, 2026 (7 months ago)
Last release
Mar 8, 2026 (7 months ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from kwannoel

Cite this page

the-controller-debugging-ui-with-playwright skill. Agent Mart. https://agentmart.dev/skills/kwannoel-the-controller-debugging-ui-with-playwright (last updated 2026-10-24)