# CI/CD for Frontend > Automated pipeline from commit to production with quality gates. Frontend architecture guidance from fearchitect, written by Abas Turabli and last reviewed 2026-06-21. Source: https://fearchitect.com/topics/ci-cd-frontend Use it as reference for the task at hand. Before changing code, check this guidance against the codebase: where the code already makes a different, deliberate choice, flag the conflict instead of rewriting it. Library APIs move faster than this guide, so confirm exact signatures in the official docs linked at the end. ## 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. ## 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. 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. 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. 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. 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. 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. 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.yml** ```yaml 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. ## Decision: 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. ## 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. ## Related topics - [CDN & Edge Caching](https://fearchitect.com/topics/cdn-edge-caching.md): Serve cached responses from PoPs near users, sparing the origin. - [Deployment Strategies & Feature Flags](https://fearchitect.com/topics/deployment-strategies-feature-flags.md): Decouple deploy from release using blue-green, canary, and flags. - [Bundle Architecture & Code Splitting](https://fearchitect.com/topics/bundle-architecture-code-splitting.md): Ship only the JS a route needs, cache the rest long-term. - [Core Web Vitals](https://fearchitect.com/topics/core-web-vitals.md): Google's three user-experience metrics: LCP, INP, and CLS. - [Frontend Testing Strategy](https://fearchitect.com/topics/frontend-testing.md): Test what the user sees, not how the code is wired. - [AI-Assisted Dev Workflow](https://fearchitect.com/topics/ai-assisted-dev-workflow.md): Using AI coding agents well without handing them ownership. ## Further reading - [size-limit — GitHub](https://github.com/ai/size-limit) - [Lighthouse CI — Getting started](https://github.com/GoogleChrome/lighthouse-ci/blob/main/docs/getting-started.md) - [Playwright — CI configuration](https://playwright.dev/docs/ci) - [Chromatic — CI setup](https://www.chromatic.com/docs/ci) - [GitHub Actions — Caching dependencies](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/caching-dependencies-to-speed-up-workflows)