CI/CD for a Next.js + Playwright App on Vercel with GitHub Actions
Lint, build, run Playwright e2e tests, then deploy your Next.js app to Vercel on every push.
This recipe pairs a Next.js app with Playwright browser tests and a Vercel deploy. CI installs dependencies, builds the app, runs Playwright against the production build, and promotes to Vercel only when the suite is green.
What the pipeline does
- install deps with npm ci
- lint and type-check
- install Playwright browsers with their OS deps
- build and start the app, then run e2e specs
- deploy to Vercel with the Vercel CLI
The workflow
Playwright spins up the built app via its webServer config, so tests hit a real Next.js server. The deploy job runs only after tests pass on the main branch.
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run lint
- run: npx playwright install --with-deps
- run: npm run build
- run: npx playwright test
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
deploy:
needs: test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm i -g vercel
- run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
- run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
- run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}Caching and speed
cache: npm restores node_modules quickly, and persisting .next/cache with actions/cache keyed on package-lock.json plus source hashes speeds incremental builds. Cache the Playwright browser binaries (~/.cache/ms-playwright) keyed on the Playwright version to skip re-downloading Chromium every run. Browser installs and e2e runs are heavy, so cheaper managed runners such as Latchkey (around 69% cheaper than GitHub-hosted) keep PR feedback fast and auto-retry transient browser-download failures.
Deploying
The deploy job uses the Vercel CLI with VERCEL_TOKEN, VERCEL_ORG_ID, and VERCEL_PROJECT_ID secrets. vercel build --prod produces a prebuilt output and vercel deploy --prebuilt --prod promotes it, so the Vercel platform does not rebuild. Capture the deployment URL from the CLI output for smoke checks.
Key takeaways
- Run Playwright against the production build so e2e tests match what ships.
- Cache the Playwright browser binaries by version to skip repeated downloads.
- Gate the Vercel deploy on a green test job and the main branch.