CI/CD Integration

Run Nightfall in your continuous integration pipeline to auto-generate themes and catch contrast regressions.

GitHub Actions

The most common setup: generate the theme and run a contrast audit on every push. The workflow starts your dev server, waits for it to be ready, then runs Nightfall:

.github/workflows/nightfall.yml
name: Nightfall Theme Generation
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

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

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

      - run: npm ci

      # Install Playwright browsers (needed for scanning)
      - run: npx playwright install chromium

      # Start dev server in background
      - run: npm run dev &

      # Wait for dev server to be ready
      - run: npx wait-on http://localhost:3000 --timeout 30000

      # Scan and generate theme
      - run: npx nightfall-css scan --url http://localhost:3000 --routes / /about /pricing
      - run: npx nightfall-css generate --format css-variables --output styles/dark-theme.css

      # Run contrast audit (fails the build if any pair is below AA)
      - run: npx nightfall-css audit --level aa --json > audit-report.json

      # Upload audit report as artifact
      - uses: actions/upload-artifact@v4
        with:
          name: nightfall-audit
          path: audit-report.json

      # Optional: export color graph
      - run: npx nightfall-css graph --output color-graph.svg
      - uses: actions/upload-artifact@v4
        with:
          name: color-graph
          path: color-graph.svg

Auto-Commit Generated Theme

Automatically commit the generated theme file back to the repository so it stays in sync with your source styles:

.github/workflows/nightfall-commit.yml
name: Auto-Generate Theme
on:
  push:
    branches: [main]
    paths:
      - 'src/**/*.css'
      - 'src/**/*.tsx'
      - 'src/**/*.jsx'

jobs:
  generate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          token: ${{ secrets.GITHUB_TOKEN }}

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

      - run: npm ci
      - run: npx playwright install chromium
      - run: npm run dev &
      - run: npx wait-on http://localhost:3000

      - run: npx nightfall-css scan --url http://localhost:3000
      - run: npx nightfall-css generate --format css-variables --output styles/dark-theme.css
      - run: npx nightfall-css audit --fix

      # Commit if there are changes
      - name: Commit generated theme
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add styles/dark-theme.css
          git diff --staged --quiet || git commit -m "chore: regenerate dark theme"
          git push

PR Contrast Check

Add a check that blocks PRs if they introduce contrast regressions:

.github/workflows/contrast-check.yml
name: Contrast Check
on: [pull_request]

jobs:
  contrast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20, cache: 'npm' }
      - run: npm ci
      - run: npx playwright install chromium
      - run: npm run dev &
      - run: npx wait-on http://localhost:3000

      - run: npx nightfall-css scan --url http://localhost:3000
      - run: npx nightfall-css audit --level aa --json > audit.json

      # Fail if compliance is below 100%
      - name: Check compliance
        run: |
          COMPLIANCE=$(node -e "const r=require('./audit.json'); console.log(r.summary.compliance)")
          if [ "$COMPLIANCE" != "1" ]; then
            echo "Contrast audit failed. See audit.json for details."
            cat audit.json | node -e "const r=require('./audit.json'); r.pairs.filter(p=>!p.pass).forEach(p=>console.log(p.foreground,'on',p.background,p.ratio+':1'))"
            exit 1
          fi

Other CI Platforms

Nightfall works in any CI environment that supports Node.js and headless browsers. The key requirements are:

  • Node.js 18+ — Required for the Nightfall CLI
  • Playwright Chromium — Run npx playwright install chromium before scanning
  • Running dev server — Nightfall scans a live URL, so your app must be running
Generic CI script
# Works in GitLab CI, CircleCI, Jenkins, etc.
npm ci
npx playwright install chromium
npm run dev &
npx wait-on http://localhost:3000
npx nightfall-css scan --url http://localhost:3000
npx nightfall-css generate --format css-variables
npx nightfall-css audit --level aa

Caching in CI

Cache the .nightfall/ directory between CI runs to speed up incremental scans:

# GitHub Actions caching
- uses: actions/cache@v4
  with:
    path: .nightfall/cache
    key: nightfall-${{ hashFiles('src/**/*.css', 'src/**/*.tsx') }}