Configuration
playwright.config.ts is the single place that controls browsers, base URL, parallelism, retries, artifacts, and timeouts. I keep one config for all environments — CI vs local is handled by process.env.CI conditions inside the same file.
A real config that actually works
This is the shape I use in every project. The key split: top-level options control the test runner (retries, workers, parallelism), use controls what every test gets by default (baseURL, viewport, credentials).
One mistake I see often: putting retries or workers inside use: {}. They don't work there — they must be at the top level.
The use section — defaults for every test
use options apply to every test automatically. The most important: baseURL lets you write page.goto('/orders') instead of the full URL everywhere. Other useful defaults:
Projects — multiple browsers or configs
Each project runs the full test suite with its own settings. The common use case: run on Chromium, Firefox, and WebKit. Another pattern: separate projects for authenticated and unauthenticated tests.
Timeouts — test, expect, action
There are three independent timeouts to know. Mixing them up is a common source of confusion.
Global setup and teardown
Global setup runs once before any test starts. I use it to seed the database, create test users, or save an auth state file that all tests share. Global teardown runs once after all tests finish — clean up.