Skip to content
fearchitect
Network & Infrastructure

CI/CD for Frontend

Automated pipeline from commit to production with quality gates.

By Abas TurabliReviewed

Summary

A frontend CI/CD pipeline runs install, typecheck, lint, test, build, and a suite of automated quality gates — bundle-size budgets via size-limit, Lighthouse CI performance assertions, and visual regression checks with Playwright or Chromatic — before promoting a preview deploy to production. The goal is catching regressions in minutes, not after a user files a bug.

Jump to the interview angle

Frontend CI/CD pipeline

A sequence of automated jobs that run on every pull request commit: install dependencies, typecheck, lint, run tests, build the app, enforce quality gates (bundle size, Lighthouse scores, visual diffs), deploy a preview environment, and — on merge — promote that build to production. Each gate is a binary pass/fail check that can block or annotate the PR. The pipeline converts human review from "does it look right" to "did it pass the gates we set when we were thinking clearly."

Pipeline stages in order

  1. 1

    Install and cache

    Run npm ci (or pnpm install --frozen-lockfile). Cache the package store keyed on the lockfile hash so repeated runs skip network I/O. GitHub Actions: use actions/setup-node with cache: 'npm' or actions/cache for pnpm.

  2. 2

    Typecheck, lint, and unit tests

    Run tsc --noEmit, then the linter, then jest or vitest. These are fast and catch most logical errors. Run in parallel where the CI runner allows — tsc and lint have no dependency on each other.

  3. 3

    Build and bundle-size gate

    Run npm run build, then npx size-limit. size-limit reads .size-limit.json, measures each JS/CSS entry point, and exits non-zero if any exceeds its budget. Catches accidental large imports before they ship.

  4. 4

    Preview deploy

    Push the build output to a preview environment (Vercel, Netlify, or your own CDN). Each PR gets a stable URL tied to its head commit. Downstream gates (Lighthouse CI, visual regression) run against this URL so they test production-equivalent serving.

  5. 5

    Lighthouse CI and visual regression

    Run lhci autorun against the preview URL to assert performance, a11y, and SEO score thresholds. Run Playwright screenshot tests or Chromatic to detect visual regressions. Lighthouse CI failures block; visual diffs post as PR comments for human review.

  6. 6

    Promotion to production

    On merge to the main branch, atomically promote the already-built and already-tested preview artifact to production. No rebuild — the same binary that passed the gates ships. Rollback is a re-promotion of the previous artifact.

GitHub Actions workflow: build + size-limit + Lighthouse CI

A single workflow file covers install, build, size-limit, and Lighthouse CI. The Lighthouse step runs against the Vercel preview URL exposed by the vercel-action output.

.github/workflows/ci.ymlyaml
name: CI

on:
  pull_request:

jobs:
  build-and-gate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm

      - run: npm ci

      # Typecheck and lint in parallel (separate steps, same job)
      - run: npx tsc --noEmit
      - run: npm run lint

      - run: npm run test -- --run   # vitest --run = non-watch mode

      - run: npm run build

      # Bundle-size gate — fails if any entry exceeds .size-limit.json budget
      - run: npx size-limit

      # Deploy preview (Vercel CLI)
      - name: Deploy preview
        id: deploy
        run: |
          PREVIEW_URL=$(npx vercel --token ${{ secrets.VERCEL_TOKEN }} --yes)
          echo "url=$PREVIEW_URL" >> "$GITHUB_OUTPUT"
        env:
          VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
          VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

      # Lighthouse CI — assert performance ≥ 90, a11y ≥ 90
      - run: npm install -g @lhci/cli
      - run: lhci autorun
        env:
          LHCI_BUILD_CONTEXT__CURRENT_HASH: ${{ github.sha }}
          LHCI_SERVER_BASE_URL: ${{ steps.deploy.outputs.url }}

size-limit exits non-zero on budget breach, blocking the job. lhci autorun reads .lighthouserc.js for URL and thresholds — configure minScore per category there.

Which gates block the merge?

Block on: typecheck failures, lint errors, failing unit tests, size-limit budget breaches, Lighthouse CI score drops. Do not block on: visual regression diffs (post as a PR comment instead) or Lighthouse best-practices warnings that don't affect users. The rule: only block if a human would always revert the merge.

Interview angle

Interviewers probe which gates you add beyond "npm test" and where you draw the line on blocking vs. non-blocking checks.

Soundbite: "A gate is only worth blocking on if a human would always revert the merge — otherwise it's noise. Bundle-size budgets and Lighthouse performance thresholds are always worth blocking on; visual diffs are better as non-blocking review aids."

Key terms

size-limit
npm tool that measures JS/CSS bundle size after build and fails CI if a configurable byte budget is exceeded.
Lighthouse CI
Google tool that runs Lighthouse against a built app in CI and asserts thresholds on performance, a11y, and SEO scores.
preview deploy
An isolated, publicly accessible build of a PR branch — each push gets its own URL for manual and automated review.
visual regression
Pixel-level or component-level screenshot comparison between a baseline and the current build, catching unintended UI changes.
promotion
Swapping the production CDN target from the current build to a new one — zero-downtime if done via atomic swap.

Further reading

Search fearchitect

Jump to a topic, mode, or action.