Skip to main content

Getting Started

This guide walks you through onboarding a repo to report its Lighthouse scores to a self-hosted LHCI server: installing the CLI, registering your repo as a project, wiring your lighthouserc.js upload config, and adding a CI step that runs on every PR.

Throughout this guide, replace https://your-lhci-server.onrender.com with the URL of your own deployed LHCI server.

Prerequisites

  • A deployed LHCI server (see the Skills Catalog if you still need to stand one up).
  • The server's basicAuth credentials (LHCI_BASIC_AUTH_USERNAME / LHCI_BASIC_AUTH_PASSWORD). These gate every route on the server, including the build-upload endpoint - not just the dashboard.
  • Node.js and a repo you want to track Lighthouse scores for.

1. Install the CLI

Install @houses/lighthouse-cli globally to get the lhci-toolkit binary:

npm install -g @houses/lighthouse-cli

2. Register your repo

Register your repo as a project on the server. This prints a build token (for CI) and a one-time admin token (save it somewhere safe - it's the only way to rename or delete the project later, and it's shown exactly once):

lhci-toolkit --server-url=https://your-lhci-server.onrender.com \
--admin-username=<username> --admin-password=<password> \
register <repo-name>
  • --server-url - base URL of your deployed LHCI server (required).
  • --admin-username / --admin-password - the server's basicAuth credentials. These are required if the server has basicAuth enabled: registration hits the same gate as the dashboard and 401s without them.
  • register <repo-name> also accepts an optional --base-branch <branch> flag (defaults to main) to set the base branch used for diff comparisons.

You can list every project already registered on the server with:

lhci-toolkit --server-url=https://your-lhci-server.onrender.com \
--admin-username=<username> --admin-password=<password> \
list

3. Wire lighthouserc.js

In the repo you just registered, add a lighthouserc.js. The server's basicAuth is mounted in front of every route, including the build-upload endpoint - so the upload block needs both token and basicAuth. Omitting basicAuth produces a 401 in CI even with a correct, valid build token:

module.exports = {
ci: {
collect: {
url: ['http://localhost:3000/'],
startServerCommand: 'npm run start',
},
upload: {
target: 'lhci',
serverBaseUrl: 'https://your-lhci-server.onrender.com',
// Project-specific - printed by `lhci-toolkit register` in step 2.
token: process.env.LHCI_BUILD_TOKEN,
// Server-wide - the same credentials used to register the project.
// Shared across every onboarded repo, not regenerated per repo.
basicAuth: {
username: process.env.LHCI_BASIC_AUTH_USERNAME,
password: process.env.LHCI_BASIC_AUTH_PASSWORD,
},
},
},
};

Adjust collect.url / startServerCommand to match how your app builds and serves locally.

4. Add the GitHub Actions CI step

Add a workflow that runs npx @lhci/cli autorun, with three repo/org secrets set as env vars: LHCI_BUILD_TOKEN (project-specific, from step 2) and LHCI_BASIC_AUTH_USERNAME / LHCI_BASIC_AUTH_PASSWORD (server-wide, shared across every onboarded repo). Also set GITHUB_TOKEN on the upload step so LHCI posts its score and comparison link directly on the PR, instead of only a link in the Actions log:

name: Lighthouse CI

on:
pull_request:
push:
branches: [main]

jobs:
lhci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 20

- run: npm ci
- run: npm run build

- run: npx @lhci/cli autorun
env:
LHCI_BUILD_TOKEN: ${{ secrets.LHCI_BUILD_TOKEN }}
LHCI_BASIC_AUTH_USERNAME: ${{ secrets.LHCI_BASIC_AUTH_USERNAME }}
LHCI_BASIC_AUTH_PASSWORD: ${{ secrets.LHCI_BASIC_AUTH_PASSWORD }}
# Enables LHCI's automatic PR status check (score + comparison
# link posted on the PR itself) instead of only a log link.
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

5. Verify it worked

  • Confirm registration succeeded: re-run the list command from step 2 and check that your repo shows up by name.
  • Confirm the upload config is correct: run npx @lhci/cli autorun locally with LHCI_BUILD_TOKEN, LHCI_BASIC_AUTH_USERNAME, and LHCI_BASIC_AUTH_PASSWORD set - it should complete with an uploaded-report URL, not a 401.
  • Confirm CI is wired correctly: open a real pull request and check that the Lighthouse CI workflow run goes green with a report link, and that a Lighthouse status check with a score appears directly on the PR (thanks to GITHUB_TOKEN in step 4).

If the upload step 401s in CI despite a build token that worked when pasted straight after register printed it, double check that upload.basicAuth is set in lighthouserc.js - the server-wide gate, not the token, is what's rejecting the request.