/** * Lighthouse CI configuration — per ADR-0017 (Performance budgets). * * Thresholds match the Google "Good" Core Web Vitals values plus the * Lighthouse Performance score floor we set as the project bar. * * Critical-routes list grows as features land. v1 only checks the * static-served portal-shell bundle (which today shows the Nx Welcome * placeholder); meaningful per-route assertions land alongside the * features that introduce those routes. */ module.exports = { ci: { collect: { // Serve the production bundle statically (no BFF needed for v1 // measurements). When real auth / routes exist, the URL list // expands to the critical-routes list documented in ADR-0017. startServerCommand: 'pnpm nx run portal-shell:serve-static', startServerReadyPattern: 'Available on:', url: ['http://localhost:4200/'], numberOfRuns: 3, settings: { // Slow-4G profile so scores are stable across CI runners and // comparable to industry public benchmarks. preset: 'desktop', // Chrome's user-namespace sandbox is disabled inside the act // runner container (AppArmor restriction on the host kernel), // so Chrome fails to launch with a "No usable sandbox" zygote // error. `--no-sandbox` is the standard Lighthouse / Puppeteer // / Playwright workaround for containerised CI: the residual // risk is acceptable because Chrome only loads our own freshly // built bundle from http://localhost:4200/ inside an ephemeral // self-hosted runner container — no untrusted content reaches // the browser process. chromeFlags: '--no-sandbox', }, }, assert: { assertions: { // Core Web Vitals (Google "Good"), per ADR-0017 'largest-contentful-paint': ['error', { maxNumericValue: 2500 }], 'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }], 'total-blocking-time': ['error', { maxNumericValue: 200 }], 'server-response-time': ['error', { maxNumericValue: 800 }], // Aggregate score — our gate is "Performance >= 90" 'categories:performance': ['error', { minScore: 0.9 }], // a11y is enforced by the dedicated a11y gate (axe-core, // ADR-0016) — keep Lighthouse a11y as a soft signal here. 'categories:accessibility': ['warn', { minScore: 0.9 }], // Best practices and SEO are advisory in this gate. 'categories:best-practices': ['warn', { minScore: 0.9 }], 'categories:seo': 'off', }, }, upload: { target: 'filesystem', outputDir: './.lighthouseci', }, }, };