
How I Wire Nx, CI/CD, and Quality Gates for AngularUX Demos (Angular 20+, Firebase, GitHub Actions)
A practical, production-grade CI/CD blueprint for Angular 20+ demos: Nx monorepo, Firebase preview channels, GitHub Actions, and quality gates that catch regressions before users do.
Pipelines should be boring, fast, and unforgiving. If a regression can slip past CI, it will slip into production.Back to all posts
I’ve shipped enough Angular dashboards to know the fail mode: a flashy demo looks great on your laptop, then wobbles in CI or dies on staging because no one gated accessibility, coverage, or performance. At AngularUX, every Angular 20+ demo—Signals, SignalStore, PrimeNG—runs through the same Nx-powered pipeline that refuses to merge risky code.
This is the platform and delivery layer I bring to Fortune 100 teams when they need a remote Angular expert. It’s pragmatic, measurable, and portable across GitHub Actions, Jenkins, or Azure DevOps. And it’s fast: PR checks typically finish in 3–7 minutes with Nx caching and affected builds.
The Scene and Why It Matters for Angular 20+ Teams
A familiar moment
It’s Wednesday, you promised a demo Friday. You add a Signals-based widget with a PrimeNG DataTable, push a PR, and hope. Without guardrails: bundle size creeps, Lighthouse tanks, and a11y violations sneak in. I’ve seen this at airlines, telecoms, and media networks.
What I do instead
This creates a repeatable path from branch to preview to main, with performance and accessibility treated as first-class build artifacts. Recruiters and directors evaluating how to hire an Angular developer get confidence from consistent delivery telemetry, not vibes.
Nx monorepo with strict boundaries
GitHub Actions that run affected targets only
Firebase preview channels per PR
Quality gates that block merges if thresholds fail
Nx Workspace Layout and Guardrails
Example project.json targets for a demo app:
Workspace layout that scales
Each demo lives under apps/, shared UI and state live under libs/. I tag libraries by domain and scope (ui, state, feature) and enforce boundaries so a feature can’t import data-access directly. That keeps PR blast radius small and speeds up affected builds.
apps/angularux-demo
libs/ui/prime
libs/state/signalstore
libs/utils/telemetry
Enforce boundaries with tags
In nx.json I define tags and rules to stop accidental coupling. This keeps the SignalStore state layer clean and makes tests deterministic.
Generators for consistency
Custom Nx generators scaffold targets (lint, test, build, e2e) and default budgets, so every demo starts with the same quality gates baked in.
nx g @nrwl/angular:application demo-ssr
nx g @nrwl/angular:lib state-session --tags=state:core,scope:session
nx g @nrwl/angular:lib ui-tables --tags=ui:prime,scope:shared
project.json Targets for Quality Gates
{
"name": "demo-analytics",
"sourceRoot": "apps/demo-analytics/src",
"projectType": "application",
"tags": ["type:app", "scope:demo", "domain:analytics"],
"targets": {
"lint": { "executor": "@angular-eslint/builder:lint" },
"type-check": { "executor": "nx:run-commands", "options": { "command": "tsc -p tsconfig.app.json --noEmit" } },
"test": { "executor": "@angular-devkit/build-angular:karma", "options": { "codeCoverage": true } },
"build": { "executor": "@angular-devkit/build-angular:browser", "options": { "budgets": [{"type":"initial","maximumWarning":"200kb","maximumError":"300kb"}] } },
"serve": { "executor": "@angular-devkit/build-angular:dev-server" },
"e2e": { "executor": "@nx/cypress:cypress", "options": { "testingType": "e2e" } },
"a11y": { "executor": "nx:run-commands", "options": { "command": "axe --exit zero http://localhost:4200 --timeout 10000" } },
"lhci": { "executor": "nx:run-commands", "options": { "command": "lhci autorun" } }
}
}Targets that CI can rely on
These are the same targets CI runs with nx affected. Lint, type-check, unit, e2e, a11y, and Lighthouse are all addressable tasks so they’re cacheable and composable.
GitHub Actions Pipeline for Affected Builds and Previews
name: ci
on:
pull_request:
branches: [ main ]
jobs:
affected:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20' }
- name: Install
run: npm ci
- name: Restore Nx Cache
uses: actions/cache@v4
with:
path: .nx/cache
key: ${{ runner.os }}-nx-${{ github.sha }}
restore-keys: ${{ runner.os }}-nx-
- name: Determine affected
run: |
npx nx print-affected --base=origin/main --head=HEAD > affected.json
- name: Lint
run: npx nx affected --target=lint --base=origin/main --head=HEAD --parallel=3
- name: Type Check
run: npx nx affected --target=type-check --base=origin/main --head=HEAD --parallel=3
- name: Unit Tests
run: npx nx affected --target=test --base=origin/main --head=HEAD --parallel=2 --code-coverage
- name: Build
run: npx nx affected --target=build --base=origin/main --head=HEAD --parallel=2
- name: Firebase Preview Deploy
run: |
npm run firebase:login-ci
npm run firebase:deploy:preview
env:
FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
- name: Lighthouse CI against Preview
run: npx nx run-many --targets=lhci --all
- name: Cypress E2E (smoke)
run: npx nx affected --target=e2e --base=origin/main --head=HEAD --parallel=1
- name: Coverage Gate
run: node tools/ci/check-coverage.mjs --min=0.85Pull request checks
We run only what changed with nx affected, using the base and head SHAs. Caching via Nx Cloud or GitHub cache cuts PR time from ~12m to ~4–7m.
lint
type-check
test (coverage)
build (budgets)
e2e (Cypress)
a11y (axe)
Lighthouse CI on preview URL
Firebase preview channels
Every PR gets a production-like URL. Stakeholders validate SSR, hydration, and PrimeNG interactions before merge.
Preview channel per PR
Auto-expire channels to control costs
Artifacts and PR comments with links
Firebase Preview and Main Release Flow
# package.json scripts excerpt
firebase:login-ci="firebase login:ci --no-localhost || true"
firebase:deploy:preview="firebase deploy --only hosting:angularux --message $GITHUB_SHA --non-interactive --project $FIREBASE_PROJECT --token $FIREBASE_TOKEN --except functions"
release:main="semantic-release"Preview deploy script
I use Firebase Hosting channels for per-PR previews. When merged to main, the pipeline promotes the channel to live and runs smoke tests post-deploy.
Main branch release
This mimics the zero-downtime release approach I ran for a global entertainment company’s employee-tracking systems—small, reversible steps.
semantic-release for versions
tags and changelog auto-generated
post-deploy e2e and Lighthouse
Quality Gates That Stop Regressions
Example TypeScript guard for Signals state changes used in tests:
Coverage and test discipline
Typed tests for Signals-based selectors and mutators keep regressions from creeping into reactive flows.
Minimum 85% per demo app
Critical paths above 90% (auth, routing, SignalStore mutators)
Accessibility (AA)
PrimeNG defaults are audited; I add tokens and semantic markup. For kiosks or offline-tolerant UIs, I also test keyboard-only flows.
axe: no serious violations
Color contrast token checks in CI
Performance and UX budgets
I treat Lighthouse reports as artifacts, not screenshots. If a demo slips on hydration or TBT, the PR is blocked.
Lighthouse: LCP < 1.8s, TBT < 100ms, CLS < 0.02
Angular build budgets per bundle
Security and dependencies
For enterprise parity, I run SCA during PRs and at nightly. SSR/Functions images get scanned in Docker with Trivy when relevant.
npm audit and license checks
Trusted Node.js/.NET APIs only
Signals Testability Snippet
import { TestBed } from '@angular/core/testing';
import { signal, computed } from '@angular/core';
class SessionStore {
private _events = signal<string[]>([]);
readonly count = computed(() => this._events().length);
push(e: string) { this._events.update(arr => [...arr, e]); }
}
describe('SessionStore', () => {
it('derives count deterministically', () => {
const store = TestBed.runInInjectionContext(() => new SessionStore());
store.push('login');
store.push('navigate');
expect(store.count()).toBe(2);
});
});Deterministic SignalStore tests
I standardize a test harness so CI can assert derived values without race conditions.
Example PR Flow: Signals + PrimeNG Widget
What changes
I push a feature that mirrors the real-time analytics stacks I’ve shipped in telecom: typed event schemas, exponential backoff, and data virtualization.
New SignalStore for session events
PrimeNG table rendering derived state
RxJS WebSocket mock for real-time updates
What CI does
GitHub Actions comments the preview URL and artifacts. If performance slipped—say TBT > 100ms—the PR would remain red until fixed.
Build: main bundle 165KB gz (budget 200KB)
Lighthouse: LCP 1.6s, TBT 40ms, CLS 0.01
axe: 0 serious violations
Coverage: 89%
Porting This Pipeline to Enterprise (GitHub, Azure DevOps, Jenkins)
Where I’ve run this
The pattern is the same: Nx for structure and speed, CI for discipline, preview envs for feedback, quality gates for safety.
Telecom ad analytics (GitHub + Actions)
Airline kiosks (Jenkins + Docker agents)
Broadcast VPS schedulers (Azure DevOps)
Risk controls
If you need an Angular consultant to standardize delivery across offshore teams, this is the playbook I bring on day one.
Feature flags for gradual rollouts
Zero-downtime deploys
Post-deploy smoke tests
Quick Start: Commands You Can Lift Today
npx create-nx-workspace@latest angularux --preset=angular-monorepo
npm i -D @angular-eslint/schematics @angular-eslint/builder
npx nx g @angular-eslint/schematics:convert-tslint-to-eslint
# Strict TS
jq '.compilerOptions += {"strict": true, "noImplicitOverride": true, "exactOptionalPropertyTypes": true}' tsconfig.base.json > tsconfig.base.tmp && mv tsconfig.base.tmp tsconfig.base.json
# Add tasks
npx nx g @nrwl/angular:application demo-analytics
npx nx g @nrwl/cypress:project --project demo-analyticsInitialize Nx and strictness
These commands set you up with Nx, Angular ESLint, and strict TS.
Add CI targets
Make tasks addressable so Nx can cache and parallelize effectively.
When to Hire an Angular Developer for Legacy Rescue
Signals to bring in help
I’ve rescued AngularJS→Angular migrations, zone.js-to-Signals refactors, and rewrote JSP apps to Angular 20. If your team is firefighting, I’ll stabilize the codebase without freezing delivery—see gitPlumbers for my code modernization services.
CI times > 20 minutes
Frequent hotfixes after release
No preview environments
Undefined budgets or a11y thresholds
How an Angular Consultant Approaches CI + Nx Integration
My 5-day rollout
This is repeatable. It’s how gitPlumbers sustains 99.98% uptime during modernizations and how IntegrityLens processed 12k+ interviews with stable releases.
Day 1: Nx assessment and tagging
Day 2: CI skeleton and caching
Day 3: Preview deploys + smoke e2e
Day 4: Quality gates (coverage, a11y, budgets)
Day 5: Teach the team, codify generators
Key takeaways
- Nx keeps AngularUX demos consistent with generators, tags, and affected-based CI to speed up checks 3–5x.
- GitHub Actions runs typed, repeatable pipelines: lint, type-check, unit, e2e, Lighthouse, a11y, and bundle budgets.
- Firebase Hosting preview channels give every PR a production-like URL for smoke tests and stakeholder review.
- Quality gates are codified thresholds: 85% coverage, AA a11y baseline, TBT < 100ms, CLS < 0.02, bundle budgets enforced.
- Signals + SignalStore demos get deterministic tests and perf telemetry so regressions surface immediately.
- This exact setup ports cleanly to Azure DevOps or Jenkins for enterprise teams with minimal changes.
Implementation checklist
- Adopt Nx workspace with tags and enforce-module-boundaries
- Enable strict TypeScript and Angular ESLint
- Add GitHub Actions with Nx affected targets and caching
- Deploy PRs to Firebase preview channels and run Lighthouse CI
- Gate merges on coverage, a11y, bundle budgets, and performance thresholds
- Add Cypress smoke tests and visual diffs for PrimeNG-heavy views
- Publish build artifacts (dist, coverage, lhci reports) to PR comments
- Use semantic-release and conventional commits for reliable versions
Questions we hear from teams
- What does an Angular consultant do for CI/CD and Nx?
- I standardize your workspace with Nx, add strict TS/ESLint, wire GitHub Actions or Azure DevOps, set preview environments, and enforce quality gates for coverage, performance, a11y, and bundle size. Teams get faster PRs and safer releases within a week.
- How long does it take to integrate this pipeline?
- Typical engagements run 1–2 weeks for demos, 2–4 weeks for large monorepos. Day 1 assessment, Day 2–3 CI and previews, Day 4–5 quality gates and training. A discovery call is usually available within 48 hours.
- What are the quality gate thresholds you enforce?
- Defaults: 85% coverage, no serious a11y violations, LCP < 1.8s, TBT < 100ms, CLS < 0.02, and Angular bundle budgets per initial/async chunks. We adjust for SSR or kiosk contexts as needed.
- Can this run on Jenkins or Azure DevOps instead of GitHub Actions?
- Yes. I’ve implemented the same Nx + quality gate pattern on Jenkins (with Docker agents) and Azure DevOps. Only the runner syntax changes; the Nx targets and gating strategy remain identical.
- How much does it cost to hire an Angular developer for this setup?
- It varies by scope. For a single app, expect a fixed-fee or short-term contract. For multi-team monorepos, I offer phased engagements. Contact me to scope—assessments are delivered within one week.
Ready to level up your Angular experience?
Let AngularUX review your Signals roadmap, design system, or SSR deployment plan.
NG Wave
Angular Component Library
A comprehensive collection of 110+ animated, interactive, and customizable Angular components. Converted from React Bits with full feature parity, built with Angular Signals, GSAP animations, and Three.js for stunning visual effects.
Explore Components