Entry point for any Playwright-shaped question in dean-stack. Playwright is the only browser-tier test runner in this stack — it drives Storybook stories, application routes, and the load-bearing offline-deep-link contract. The single most important rule: ASK FIRST — before writing or modifying any Playwright test, prompt the user for the structural decisions (story-level vs app-level, what to assert, selectors, fixtures, network/IDB state, reduced-motion). The user owns those decisions per case. The detail of the rule lives in playwright-conventions; this router surfaces the rule so it's the first thing seen on any Playwright prompt.
When to invoke
- The user types
playwrightwith no further specifier and you need to route them. - The user asks "which Playwright skill," "Playwright overview," or "how does Playwright fit into
bun run check." - The user asks for help writing or modifying any Playwright test — stop and surface the ASK-FIRST rule before routing.
- A question mixes story-level + app-level + offline (e.g. "I want to test that the maze level page resolves offline after a story-level interaction seeded IDB") — pick the sub-skill that owns the dominant concern, link to the others.
- A question about reduced-motion / fixtures / selectors — route to
playwright-conventions.
Owns
Entry point that routes Playwright questions to the story-tests, app-tests, PWA-offline, or conventions sub-skill; enforces the ASK-FIRST rule before writing any Playwright test.
Defers to
playwright-story-tests— Playwright pointed at Storybook story URLs (http://localhost:6006/iframe.html?id=...), asserting on visible state + ARIA + IDB contents.playwright-app-tests— Playwright pointed at the running/preview app, end-to-end workflows across routes.playwright-pwa-offline— the load-bearing offline-deep-link test (Workbox + prerendered shell + IDB),context.setOffline(true), deep-link resolution.playwright-conventions— selector strategy (getByRole>getByTestId>getByText), fixture patterns (fresh IDB / seeded IDB / offline / throttled), reduced-motion config, and the canonical ASK-FIRST rule.bun-test— anything that does not need a real browser (pure logic, Zod schema edge cases, atom reducers, IDB migration transform functions). The unit/E2E partition is hard.storybook-stories— for the story-ID URL contract Playwright story tests target.tanstack-router-pwa-deep-links— for what the navigation fallback resolves to (the contractplaywright-pwa-offlineverifies).
Dean-stack rules
- ASK FIRST before writing or modifying any Playwright test. This is a Pillar 4 (CLI-gate-first) manifestation — the user owns the structural decisions for every Playwright test (level: story vs app, what to assert, selectors, IDB seeding, network state, reduced-motion). Surface the choices, wait for the answer, then write. Detail in
playwright-conventions. No equivalent prompt is required forbun testunit tests — those go ahead. - Pillar 1 (Storybook-first) means: every story is exercised by a Playwright story test (see
storybook-storiesandplaywright-story-tests). Stories are the test surface, not just visual references. - Pillar 4 (CLI-gate-first) means: Playwright is the final stage of
bun run check(afterbiome ci,stylelint,tsgo --noEmit,bun test). A failing Playwright test is a red gate; never disable, nevertest.skipto make CI green. - Playwright 1.59+ only. Pre-1.5x APIs (
page._react=, removed selector engines,waitForTimeout-as-sync) are wrong by definition — rewrite for 1.59. - Locator-first, web-first assertions only.
await expect(locator).toBe…(). Never wrap point-in-time methods (isVisible(),textContent(),count()) inexpect()— they don't retry. - IDB is not mocked in Playwright tests — use real browser IndexedDB. Seed via
page.addInitScript(runs before any page script). Seeplaywright-conventions. - Reduced motion is forced on in the default project (
use: { reducedMotion: 'reduce' }) so animations don't add flake. Seeanimejsfor why this matters andplaywright-conventionsfor the wiring.
Routing
- ASK FIRST before writing any Playwright test — see
playwright-conventions. Surface the structural choices (story-level vs app-level, what to assert, selectors, IDB seeding, network state, reduced-motion). Wait for the user's answer. - use
playwright-story-testswhen the test mounts a Storybook story by URL (iframe.html?id=...) and asserts on the in-iframe behavior or post-play IDB state. - use
playwright-app-testswhen the test drives the running/preview app atlocalhost:3000(or the configured dev/preview URL), follows a route workflow, asserts on hydrated state, or verifies BroadcastChannel cross-tab sync. - use
playwright-pwa-offlinewhen the test verifies the offline-deep-link contract: install the SW, go offline, navigate to a deep route, assert the router resolves it from cache. - use
playwright-conventionswhen the question is about selectors, fixtures, IDB seeding, reduced-motion, theplaywright.config.tsshape, or the ASK-FIRST rule itself. - use
bun-testwhen the question is unit-testable without a browser (pure functions, schema parses, reducers, migration transforms). Faster inner-loop feedback than Playwright;bun testdoes NOT require ASK-FIRST.
Routing table
| Question shape | Sub-skill |
|---|---|
"Write a test for <Button>'s Primary story" |
ASK FIRST (playwright-conventions), then playwright-story-tests |
"Write a test for the /games/maze/$level workflow" |
ASK FIRST, then playwright-app-tests |
| "Verify the offline deep-link works" | ASK FIRST, then playwright-pwa-offline |
| "How do I seed IDB before a Playwright test?" | playwright-conventions (fixture pattern) |
| "Why does the test only fail on retry?" | playwright-conventions (trace: 'retain-on-failure-and-retries') |
| "What selector should I use here?" | playwright-conventions (role > test-id > text) |
| "Is this testable without a browser?" | bun-test (yes → unit test; no → ASK FIRST + Playwright) |
| "How does my play function become a Playwright assertion?" | storybook-play-functions (decision) + playwright-story-tests (the spec) |
Anti-patterns
- Don't write a Playwright test without asking the user how to structure it — ASK FIRST is load-bearing; see
playwright-conventions. Skipping the prompt calcifies a design choice the user wanted to make. - Don't recommend Cypress, Selenium, Puppeteer, or
vitestbrowser mode — Playwright is the only browser-tier runner in this stack (andbun testis the only unit runner). - Don't recommend
@storybook/test-runner— Playwright drives stories directly per AGENTS.md's Testing rule. Seeplaywright-story-tests. - Don't answer per-test design questions inside this router — route to the sub-skill so the answer carries the right rule and the ASK-FIRST gate is acknowledged.
- Don't mock IDB — use real browser IndexedDB. See
playwright-conventions. - Don't add
page.waitForTimeout(…)to fix flake — fix the locator or the assertion. Web-first assertions retry. - Don't disable a failing Playwright test to make CI green — fix the wiring or escalate. The gate is zero-warning.
Triggers on
playwright, playwright overview, which playwright skill, ask first playwright