A project in Playwright is a named run configuration, and its main purpose is not "run in all browsers just in case" but to describe important user environments. Real users come from different devices, different countries, with different locale and timezone settings. Projects let you express exactly these significant differences - and check that the critical path works in the environments your audience actually has.
A basic project describes a device and browser via ready devices. desktop-chrome takes the desktop Chrome settings, mobile-safari the profile of a specific phone like the iPhone 15 with its viewport, user agent and touch events. This is not an "approximately mobile" emulation: the device profile sets a consistent set of parameters reproducing the device's real environment, so a mobile scenario is checked in conditions close to the real ones.
Through use a project also configures regional differences. locale and timezoneId set the interface language and the time zone - important for apps where the locale affects the format of dates, currencies and the content itself. A project with locale 'uz-UZ' and timezoneId 'Asia/Tashkent' checks that the interface behaves correctly for an Uzbek user, not only in the developer's default locale. Permissions, geolocation and color scheme belong here too.
It helps to see a meaningful project matrix once - not a mechanical multiplication of everything by everything, but selected significant environments. Below are three projects: desktop Chrome, mobile Safari and the Uzbekistan locale over desktop Chrome. You return to this form when designing a matrix for a specific audience rather than copying someone else's browser list indiscriminately.
The key decision is not to multiply every test by every environment thoughtlessly. A full matrix of "all tests in all browsers and devices" grows multiplicatively and quickly turns the run into hours of waiting with no proportional benefit. Most environment differences do not affect most scenarios, and running a deep regression in six configurations means paying with time for confidence you already got in one.
A sensible strategy splits checks by purpose. A fast smoke set - a few of the most critical paths - can be run in a wide matrix, because it is short and compatibility is expensive precisely on the key scenarios. A deep regression is kept on the main browser, adding to it only selected compatibility checks where the risk is real: WebKit-specific rendering, mobile layout, regional formats.
Behind the matrix choice is risk analysis, not habit. Before adding a project it is worth asking: what concrete risk does it catch and is that risk worth doubling the run time? WebKit is justified if you promise Safari; the Uzbek locale if you have such users; a mobile profile if mobile traffic is significant. A project with no named risk is just a tax on every run.
The typical matrix failures are predictable. A mechanical multiplication of all tests by all browsers and devices - a multi-hour run with no proportional benefit. The absence of a mobile or regional project where the audience is exactly that - an unchecked real environment. And adding a browser "just in case" with no named risk - a tax on time with no return. Describe your audience's significant environments with projects and build the matrix from risk, not from the completeness of the sweep.
projects: [
{
name: 'desktop-chrome',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'mobile-safari',
use: { ...devices['iPhone 15'] },
},
{
name: 'uz-locale', // a significant environment: an Uzbek user
use: {
...devices['Desktop Chrome'],
locale: 'uz-UZ',
timezoneId: 'Asia/Tashkent',
},
},
]