home / skills / dexploarer / claudius-skills / lighthouse-ci-integrator
/examples/intermediate/performance-skills/lighthouse-ci-integrator
This skill automates performance testing and Core Web Vitals tracking with Lighthouse CI in CI/CD, enforcing budgets and surfacing trends.
npx playbooks add skill dexploarer/claudius-skills --skill lighthouse-ci-integratorReview the files below or copy the command above to add this skill to your agents.
---
name: lighthouse-ci-integrator
description: Integrates Lighthouse CI for automated performance testing, Core Web Vitals tracking, and regression detection in CI/CD pipelines. Use when user asks to "setup Lighthouse CI", "add performance testing", "monitor Core Web Vitals", or "prevent performance regressions".
allowed-tools: [Write, Read, Bash, Glob]
---
# Lighthouse CI Integrator
Sets up Lighthouse CI to automatically test performance, accessibility, SEO, and best practices in your CI/CD pipeline with budget enforcement and trend tracking.
## When to Use
- "Setup Lighthouse CI"
- "Add performance testing to CI/CD"
- "Monitor Core Web Vitals"
- "Prevent performance regressions"
- "Track Lighthouse scores"
- "Setup performance budgets"
## Instructions
### 1. Install Lighthouse CI
```bash
npm install --save-dev @lhci/cli
# or
yarn add --dev @lhci/cli
```
### 2. Create Configuration File
**lighthouserc.js:**
```javascript
module.exports = {
ci: {
collect: {
// URLs to test
url: [
'http://localhost:3000/',
'http://localhost:3000/about',
'http://localhost:3000/products',
],
// Number of runs per URL
numberOfRuns: 3,
// Start server before collecting
startServerCommand: 'npm run serve',
startServerReadyPattern: 'Server listening',
// Or use static directory
staticDistDir: './dist',
// Settings
settings: {
preset: 'desktop', // or 'mobile'
// Throttling
throttling: {
rttMs: 40,
throughputKbps: 10240,
cpuSlowdownMultiplier: 1,
},
// Screen emulation
screenEmulation: {
mobile: false,
width: 1350,
height: 940,
deviceScaleFactor: 1,
disabled: false,
},
},
},
upload: {
target: 'temporary-public-storage',
// Or use LHCI server
// target: 'lhci',
// serverBaseUrl: 'https://your-lhci-server.com',
// token: process.env.LHCI_TOKEN,
},
assert: {
preset: 'lighthouse:recommended',
assertions: {
// Performance
'categories:performance': ['error', { minScore: 0.9 }],
'first-contentful-paint': ['warn', { maxNumericValue: 2000 }],
'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
'total-blocking-time': ['warn', { maxNumericValue: 300 }],
'speed-index': ['warn', { maxNumericValue: 3000 }],
'interactive': ['warn', { maxNumericValue: 3500 }],
// Accessibility
'categories:accessibility': ['error', { minScore: 0.95 }],
// Best Practices
'categories:best-practices': ['error', { minScore: 0.9 }],
// SEO
'categories:seo': ['warn', { minScore: 0.9 }],
// Resource budgets
'resource-summary:script:size': ['error', { maxNumericValue: 500000 }],
'resource-summary:stylesheet:size': ['warn', { maxNumericValue: 100000 }],
'resource-summary:image:size': ['warn', { maxNumericValue: 1000000 }],
'resource-summary:font:size': ['warn', { maxNumericValue: 100000 }],
'total-byte-weight': ['warn', { maxNumericValue: 2000000 }],
// Other metrics
'uses-http2': 'error',
'uses-webp-images': 'warn',
'offscreen-images': 'warn',
'unused-css-rules': 'warn',
'unused-javascript': 'warn',
'modern-image-formats': 'warn',
'uses-optimized-images': 'warn',
'uses-text-compression': 'error',
'uses-responsive-images': 'warn',
},
},
},
};
```
**Mobile Configuration:**
```javascript
// lighthouserc.mobile.js
module.exports = {
ci: {
collect: {
url: ['http://localhost:3000/'],
numberOfRuns: 3,
settings: {
preset: 'mobile',
throttling: {
rttMs: 150,
throughputKbps: 1638,
cpuSlowdownMultiplier: 4,
},
screenEmulation: {
mobile: true,
width: 412,
height: 823,
deviceScaleFactor: 2.625,
disabled: false,
},
formFactor: 'mobile',
},
},
assert: {
assertions: {
'categories:performance': ['error', { minScore: 0.85 }],
'first-contentful-paint': ['error', { maxNumericValue: 2500 }],
'largest-contentful-paint': ['error', { maxNumericValue: 4000 }],
},
},
},
};
```
### 3. Add npm Scripts
**package.json:**
```json
{
"scripts": {
"build": "next build",
"serve": "next start",
"lhci:collect": "lhci collect",
"lhci:assert": "lhci assert",
"lhci:upload": "lhci upload",
"lhci:autorun": "lhci autorun",
"lhci:mobile": "lhci autorun --config=lighthouserc.mobile.js",
"lhci:desktop": "lhci autorun --config=lighthouserc.js"
}
}
```
### 4. GitHub Actions Integration
**.github/workflows/lighthouse-ci.yml:**
```yaml
name: Lighthouse CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build application
run: npm run build
- name: Run Lighthouse CI (Desktop)
run: npm run lhci:desktop
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
- name: Run Lighthouse CI (Mobile)
run: npm run lhci:mobile
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
- name: Upload Lighthouse results
uses: actions/upload-artifact@v3
if: always()
with:
name: lighthouse-results
path: .lighthouseci
```
**With deployment preview (Vercel/Netlify):**
```yaml
name: Lighthouse CI with Preview
on:
pull_request:
branches: [main]
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Wait for Vercel Preview
uses: patrickedqvist/[email protected]
id: wait-for-vercel
with:
token: ${{ secrets.GITHUB_TOKEN }}
max_timeout: 300
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install Lighthouse CI
run: npm install -g @lhci/cli
- name: Run Lighthouse CI
run: |
lhci autorun --url=${{ steps.wait-for-vercel.outputs.url }}
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
```
### 5. GitLab CI Integration
**.gitlab-ci.yml:**
```yaml
lighthouse:
stage: test
image: node:18
before_script:
- npm ci
script:
- npm run build
- npm run lhci:autorun
artifacts:
paths:
- .lighthouseci
expire_in: 1 week
only:
- merge_requests
- main
```
### 6. Setup LHCI Server (Optional)
**Docker Compose for LHCI Server:**
```yaml
# docker-compose.lhci.yml
version: '3.8'
services:
lhci-server:
image: patrickhulce/lhci-server:latest
ports:
- '9001:9001'
environment:
LHCI_STORAGE_METHOD: sql
LHCI_STORAGE_SQL_DIALECT: postgres
LHCI_STORAGE_SQL_DATABASE: lighthouse
LHCI_STORAGE_SQL_USERNAME: postgres
LHCI_STORAGE_SQL_PASSWORD: postgres
LHCI_STORAGE_SQL_HOST: postgres
depends_on:
- postgres
postgres:
image: postgres:14
environment:
POSTGRES_DB: lighthouse
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
volumes:
- lhci-postgres-data:/var/lib/postgresql/data
volumes:
lhci-postgres-data:
```
**Start server:**
```bash
docker-compose -f docker-compose.lhci.yml up -d
```
**Create project:**
```bash
lhci wizard
# Follow prompts to create project and get token
```
### 7. Budget.json (Alternative Format)
**budget.json:**
```json
[
{
"path": "/*",
"timings": [
{
"metric": "interactive",
"budget": 3500
},
{
"metric": "first-meaningful-paint",
"budget": 2000
}
],
"resourceSizes": [
{
"resourceType": "script",
"budget": 300
},
{
"resourceType": "image",
"budget": 500
},
{
"resourceType": "stylesheet",
"budget": 100
},
{
"resourceType": "font",
"budget": 100
},
{
"resourceType": "total",
"budget": 1000
}
],
"resourceCounts": [
{
"resourceType": "third-party",
"budget": 10
}
]
}
]
```
### 8. Custom Audits
**custom-audit.js:**
```javascript
// custom-audit.js
class CustomAudit extends Lighthouse.Audit {
static get meta() {
return {
id: 'custom-performance-check',
title: 'Custom Performance Check',
failureTitle: 'Custom performance check failed',
description: 'Validates custom performance requirements',
requiredArtifacts: ['devtoolsLogs', 'traces'],
};
}
static audit(artifacts, context) {
// Custom audit logic
const score = 1; // 0-1
return {
score,
numericValue: 100,
displayValue: '100ms',
};
}
}
module.exports = CustomAudit;
```
**Use in lighthouserc.js:**
```javascript
module.exports = {
ci: {
collect: {
settings: {
plugins: ['./custom-audit.js'],
},
},
},
};
```
### 9. PR Comments Integration
**Comment on PR with results:**
```yaml
# .github/workflows/lighthouse-ci.yml
- name: Comment PR with results
uses: treosh/lighthouse-ci-action@v9
with:
urls: |
https://example.com
https://example.com/about
uploadArtifacts: true
temporaryPublicStorage: true
```
### 10. Monitoring and Alerts
**Slack notifications:**
```yaml
# .github/workflows/lighthouse-ci.yml
- name: Notify Slack
if: failure()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 'Lighthouse CI failed! Performance regression detected.'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
```
**Email notifications:**
```yaml
- name: Send email notification
if: failure()
uses: dawidd6/action-send-mail@v3
with:
server_address: smtp.gmail.com
server_port: 465
username: ${{ secrets.EMAIL_USERNAME }}
password: ${{ secrets.EMAIL_PASSWORD }}
subject: Lighthouse CI Failed
body: Performance regression detected in ${{ github.repository }}
to: [email protected]
```
### 11. Generate Reports
**HTML Report:**
```bash
# Generate HTML report locally
lhci collect
lhci upload --target=filesystem --outputDir=./lighthouse-reports
# Open report
open ./lighthouse-reports/index.html
```
**JSON Report:**
```javascript
// parse-lighthouse-results.js
const fs = require('fs');
const results = JSON.parse(fs.readFileSync('.lighthouseci/manifest.json'));
results.forEach(result => {
const report = JSON.parse(fs.readFileSync(result.jsonPath));
console.log('URL:', report.finalUrl);
console.log('Performance:', report.categories.performance.score * 100);
console.log('Accessibility:', report.categories.accessibility.score * 100);
console.log('Best Practices:', report.categories['best-practices'].score * 100);
console.log('SEO:', report.categories.seo.score * 100);
console.log('---');
});
```
### 12. Performance Budgets
**Strict budgets:**
```javascript
assertions: {
// Core Web Vitals (strict)
'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
'first-input-delay': ['error', { maxNumericValue: 100 }],
// Page weight
'total-byte-weight': ['error', { maxNumericValue: 1500000 }], // 1.5MB
'dom-size': ['warn', { maxNumericValue: 800 }],
// JavaScript
'bootup-time': ['warn', { maxNumericValue: 3500 }],
'mainthread-work-breakdown': ['warn', { maxNumericValue: 4000 }],
}
```
### Best Practices
**DO:**
- Run Lighthouse CI on every PR
- Set realistic performance budgets
- Test both mobile and desktop
- Monitor trends over time
- Use temporary storage for PRs
- Setup LHCI server for history
- Test multiple pages
- Include authentication flows
**DON'T:**
- Set budgets too strict initially
- Only test homepage
- Ignore accessibility scores
- Skip mobile testing
- Test only in production
- Forget to warm up the server
- Ignore flaky metrics
## Checklist
- [ ] Lighthouse CI installed
- [ ] Configuration file created
- [ ] Performance budgets set
- [ ] CI/CD integration added
- [ ] Multiple URLs configured
- [ ] Mobile + Desktop testing
- [ ] Assertions configured
- [ ] PR comments enabled
- [ ] Monitoring setup
- [ ] Team notified of new checks
This skill integrates Lighthouse CI into your CI/CD pipeline to automate performance testing, Core Web Vitals tracking, and regression detection. It provisions configs, npm scripts, and CI workflow steps to run desktop and mobile audits, enforce budgets, and surface failures on PRs. Use it to get repeatable Lighthouse reports, trend history, and alerting for regressions.
The integration installs @lhci/cli, adds lighthouserc configuration (desktop and mobile), and wires lhci commands into npm scripts and CI jobs. It collects multiple runs per URL, asserts scores and metrics against configured budgets, uploads results (temporary storage or LHCI server), and can post PR comments or notifications on failures. Optional custom audits, a self-hosted LHCI server, and report generation are supported.
Do I need a self-hosted LHCI server?
No. Use temporary-public-storage for PRs initially; add a self-hosted LHCI server when you need retained history and trend analysis.
How do I reduce flaky results?
Collect multiple runs per URL, run separate mobile/desktop configs, warm up the server, and use consistent throttling and emulation settings.
Can I add custom audits?
Yes. Implement a Lighthouse Audit plugin and reference it in lighthouserc plugins to include custom checks.