Use when shaping a Playwright suite — locator strategy, Page Object boundaries, fixture composition, flake-prevention architecture, CI-vs-local split — even on 'design our E2E tests'.
Scanned 6/5/2026
Install via CLI
openskills install event4u-app/agent-config---
model_tier: high
name: playwright-architect
description: "Use when shaping a Playwright suite — locator strategy, Page Object boundaries, fixture composition, flake-prevention architecture, CI-vs-local split — even on 'design our E2E tests'."
personas:
- frontend-engineer
domain: quality
recommended_for_user_types: [developer]
workspaces:
- engineering
packs:
- engineering-base
---
# playwright-architect
> Architectural lens **above** the existing tactical
> [`playwright-testing`](../playwright-testing/SKILL.md). Decides
> locator philosophy, Page Object boundaries, fixture composition,
> and the CI-vs-local split *before* the first test is written.
> The `playwright-testing` skill handles concrete assertions,
> selectors, and visual-regression mechanics once the design is
> locked.
## When to use
- A new Playwright suite is starting and the directory shape, fixture
hierarchy, and locator strategy are unsettled.
- An existing suite has flake > 2 % runs, slow CI (> 10 min), or a
god-test file mixing unrelated journeys.
- A second app / surface (admin, mobile-web, embedded widget) needs
to share fixtures with the main suite.
- German triggers: "Playwright Setup planen", "Page Objects schneiden",
"warum flaket der Test?".
Do NOT use when:
- A single test fails and the question is the assertion or selector
— route to [`playwright-testing`](../playwright-testing/SKILL.md).
- The platform is mobile-native (Detox, Appium, Maestro) — route to
[`mobile-e2e-strategy`](../mobile-e2e-strategy/SKILL.md).
- Unit / component tests are the question — Playwright is the wrong
tool; route to the stack-specific testing skill.
## Procedure
### 1. Inspect the suite, pick the locator philosophy
Review existing tests for current locator patterns; the established
strategy wins unless it is the "last resort" tier. One philosophy
per suite, written into `CONTRIBUTING-tests.md`:
| Strategy | When |
|---|---|
| `getByRole` + accessible name | Default — couples tests to the user contract, not markup |
| `data-testid` | Legacy markup, third-party widgets, hash-suffixed CSS modules |
| Text content (`getByText`) | Static marketing pages, copy-stable surfaces |
| CSS / XPath | Last resort — every use is a debt entry |
Mixing strategies inside one test file is the smell — pick one and
fall back only with comment.
### 2. Cut Page Object boundaries
A Page Object owns: (a) one URL or one logical surface (modal,
drawer), (b) the locators on that surface, (c) the **actions** a
user can perform there. It does NOT own assertions about other
surfaces or test setup. Boundary rule: if two POs need to call
each other, introduce a **flow object** (`SignupFlow`) above them.
### 3. Compose fixtures, don't inherit
Playwright fixtures stack via `test.extend()`. Three layers max:
| Layer | Owns |
|---|---|
| Base | Browser, context, storageState, network mocks |
| Auth | Logged-in user states (admin, member, guest) |
| Domain | Pre-seeded entities for a journey |
Deeper stacks become un-debuggable; flatten by extracting helpers.
### 4. Plan flake prevention before the first failure
Bake in: auto-retry on network idle, soft assertions for parallel
checks, deterministic seed data, time freezing (`page.clock`),
explicit `expect.poll()` for eventual consistency, no
`waitForTimeout` ever. If a test needs `sleep`, the fixture is
wrong.
### 5. Split CI vs local execution
Local: headed browser, single worker, slowMo enabled, video off,
trace-on-retry. CI: headless, sharded workers (2–8), trace-on-first-retry,
video-on-failure, Github reporter + HTML. Document both in
`playwright.config.ts`; do not let local config leak into CI.
## Output format
Return:
1. Locator + Page Object plan — chosen strategy, PO list with surface
and action count, flow objects when ≥ 2 POs collaborate.
2. Fixture composition — base / auth / domain layer with what each
layer sets up.
3. Parallelism + flake budget — worker count, shard strategy,
isolation, target flake ceiling, CI-vs-local config delta.
Concrete shape:
```
Suite: <name>
Locator strategy: <getByRole | data-testid | text | mixed (justified)>
Page Objects: <list with surface owned + action count>
Flow objects: <list — only when ≥ 2 POs collaborate>
Fixture layers: base / auth / domain — each with what it sets up
Parallelism: <workers, shards, isolation strategy>
Flake budget: ≤ 1 % failure on green main; alert threshold
CI-vs-local: <key config delta, one bullet each>
```
## Gotcha
- `page.waitForSelector` is almost always wrong — `expect(locator).toBeVisible()`
has built-in retry. The former teaches devs to think "wait, then
assert" instead of "auto-retry assertion".
- Storage-state reuse across workers requires cookie domain
isolation; the same `auth.json` across two browsers in parallel
shares a session and corrupts state.
- Visual regression in CI requires identical fonts and renderer —
pin the Docker image, never run visual tests against host
Chromium.
- One Page Object per URL **looks** clean but creates god-objects
for SPA routes; cut by *user surface*, not by `pathname`.
## Do NOT
- Do NOT cite this skill alongside [`playwright-testing`](../playwright-testing/SKILL.md)
in the same step — they sit at different tiers; pick one per phase.
- Do NOT design suites for component tests with this skill —
Playwright Component Testing has different fixture rules; route
there instead.
- Do NOT promise zero flake; budget for ≤ 1 % and instrument the
metric. Zero is a goal that disguises silent retries.
- Do NOT push the architecture into the tracker as code AC — output
is a design note for refinement, not implementation steps.
No comments yet. Be the first to comment!