Claude Code כותב קוד פרונטאנד בלי לראות את התוצאה בפועל. שילוב של Playwright פותר את הבעיה הזו - ומשנה לחלוטין את מהירות הפיתוח.
כשבניתי דשבורד ב-Next.js באמצעות Claude Code, שמתי לב לנקודת תורפה מעניינת: ה-AI כתב קוד נקי ומובנה היטב, אבל אף אחד מאיתנו לא יכול היה לראות איך הוא נראה בפועל בדפדפן בזמן אמת. הייתי צריך לרענן את הדף ידנית ולבדוק כל שינוי בעצמי. מעגל המשוב הזה – כתיבה, המתנה, בדיקה ידנית וכתיבה מחדש – יצר חיכוך מיותר ועיכב את העבודה.
כדי לפתור את זה, החלטתי להוסיף את Playwright ככלי תצפית (Observation tool) – לא למטרת הרצת בדיקות (tests), אלא פשוט כדי לתת ל-AI "עיניים".
מה זה בכלל "כלי תצפית"?
עבור רוב המפתחים, השם Playwright מתקשר מיד לאוטומציה של בדיקות – סוויטות בדיקה (test suites), בדיקות נכונות (assertions) ותהליכי CI/CD. זהו אכן שימוש קלאסי, אך קיים דפוס פשוט ועוצמתי בהרבה: פתיחת דפדפן מול האפליקציה וצילום המתרחש בזמן אמת.
באמצעות פקודה אחת פשוטה, אני יכול להפיק צילום מסך (screenshot) מלא של מצב האפליקציה הנוכחי, ללכוד שגיאות בקונסול (console errors) או קריסות של הדף ברגע שהן מתרחשות, ולעקוב אחר הניווט והאינטראקציה של הדפדפן – והכל ישירות מהטרמינל.
זו אינה בדיקה (testing) במובן המסורתי; זוהי תצפית חיה (observation).
איך הגדרתי את זה?
תהליך ההגדרה בפרויקט שלי היה פשוט ומהיר:
- התקנה כ-dev dependency בתיקיית ה-
frontend/– גרסת Playwright 1.59.1, עם דפדפן Chromium בלבד (כדי לחסוך במשאבים). - קובץ קונפיגורציה שנוסף ל-
.gitignore– קובץplaywright.config.tsמוגדר עםbaseURL: http://localhost:3003והשהיה שלslowMo: 800כדי שנוכל לעקוב בעין אחרי המתרחש. - תיקיית סקריפטים תחת
.gitignore– שומרת על ה-repository נקי ומבטיחה שהסקריפטים המקומיים לא יידחפו ל-Git. - פקודת צילום מסך מהירה – פקודה קצרה אחת שמצלמת את העמוד במלואו, וזהו.
בנוסף, הגדרתי התקנה גלובלית של Playwright שאינה תלויה בפרויקט ספציפי. היא מאפשרת לי לצלם כל כתובת URL או קובץ HTML מקומי בפקודה אחת מהירה – פתרון זריז שניתן להריץ באמצע סשן עבודה בלי לקטוע את חוט המחשבה.
תובנה חשובה מהעבודה היומיומית: שימוש ב-page.locator('textarea') התגלה כאמין בהרבה מ-getByPlaceholder() המבוסס על ביטויים רגולריים (regex). בחירת אלמנט לפי placeholder עלולה להיראות נכונה "על הנייר" אך להיכשל בשקט, בעוד שסלקטורים ישירים לאלמנטים פשוט עובדים.
איך זה משפיע על זרימת העבודה בפועל?
ברגע ש-Claude Code מסיים לכתוב רכיב UI, אני מפיק צילום מסך שלו מיד. אם משהו נראה לא תקין, יש לנו תמונה מוחשית וברורה לעבוד איתה – במקום להסתמך על ניחושים או תיאורים מילוליים. ה-AI יכול לנתח ישירות את צילום המסך ולהגיב למראה האמיתי של הרכיב.
גם לוגים של הקונסול (console logs) משחקים כאן תפקיד קריטי. לכידה של כל console.error או pageerror ברגע הופעתם מאפשרת לי לזהות שגיאות לפני שהן נערמות – במקום לגלות אותן רק דקות ארוכות לאחר מכן כשנזכרים לפתוח את הדפדפן ידנית.
תחשבו על זה כמו על מצלמה המוצבת מעל קו ייצור: בקרת איכות אמיתית אינה מתבצעת על ידי קריאה חוזרת של הוראות ההרכבה, אלא על ידי בחינה ישירה של המוצר המוגמר.
למה זה חשוב במיוחד עכשיו?
חברת Anthropic הכפילה לאחרונה את מגבלות הקצב (rate limits) של Claude Code בכל תוכניות השימוש והסירה לחלוטין את מגבלות העומס (throttling) בשעות השיא. המשמעות היא סשנים ארוכים ורציפים בהרבה, ויכולת לכתוב נפח גדול בהרבה של קוד בכל הרצה.
ככל ש-Claude Code מייצר יותר קוד בכל סשן, כך גובר הצורך בכלי מהיר לבחינת התוצאות ללא הפרעה לזרימת העבודה וללא צורך בבדיקות ידניות חוזרות ונשנות. שילוב של Playwright בלולאת הפיתוח (feedback loop) סוגר את הפער הזה בצורה חלקה וללא סרבול מיותר.
מגדירים פעם אחת, מוסיפים ל-.gitignore, ונהנים מסביבת עבודה משודרגת בכל סשן מחדש.
העתיקו את הסקריפט לסוכן שלכם
אני משתמש ב-"Skill" ייעודי של Claude Code כדי להגדיר את התשתית הזו אוטומטית בכל פרויקט חדש. שמרו את התוכן שלהלן כקובץ בשם .claude/commands/playwright-setup.md בפרויקט שלכם. לאחר מכן, פשוט הריצו את הפקודה /playwright-setup מול Claude והוא כבר יטפל בכל השאר.
# 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 `package.json` dev script for `--port` flag. If not found, ask the user directly. 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 the 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}`));
```