---
title: "Run Lighthouse in GitHub Actions to block SEO regressions before merge"
description: "Audit every pull request with Lighthouse CI in GitHub Actions, fail merges on SEO and Core Web Vitals regressions, and alert the team."
canonical: "https://scalewithsearch.com/articles/lighthouse-github-actions-seo"
date: "2026-03-20"
modified: "2026-09-25"
---
## Site navigation

- [Scale With Search](https://scalewithsearch.com/)
- Real estate
  - Real estate
    - [Real estate](https://scalewithsearch.com/for/real-estate)
- Work
  - Start here
    - [Send your brief](https://scalewithsearch.com/work#send-your-brief)
    - [Prepare your six-question brief](https://scalewithsearch.com/work#prepare-your-six-question-brief)
  - Build
    - [Site build, content library with SEO, signal desk](https://scalewithsearch.com/work)
- For your business
  - Trades and home services
    - [Auto body and collision shops](https://scalewithsearch.com/for/auto-body-and-collision-shops)
    - [Foundation and home repair contractors](https://scalewithsearch.com/for/foundation-and-home-repair)
    - [Garage door and fencing contractors](https://scalewithsearch.com/for/garage-door-and-fencing-contractors)
    - [HVAC contractors](https://scalewithsearch.com/for/hvac-contractors)
    - [Janitorial and commercial cleaning companies](https://scalewithsearch.com/for/janitorial-and-commercial-cleaning)
    - [Locksmiths](https://scalewithsearch.com/for/locksmiths)
    - [Moving companies](https://scalewithsearch.com/for/moving-companies)
    - [Pest control companies](https://scalewithsearch.com/for/pest-control-companies)
    - [Plumbing and electrical contractors](https://scalewithsearch.com/for/plumbing-and-electrical-contractors)
    - [Restoration and water or fire damage companies](https://scalewithsearch.com/for/restoration-and-water-fire-damage)
    - [Roofing companies](https://scalewithsearch.com/for/roofing-companies)
    - [Towing companies](https://scalewithsearch.com/for/towing-companies)
    - [Tree services and landscaping companies](https://scalewithsearch.com/for/tree-services-and-landscaping)
    - [Solar installers](https://scalewithsearch.com/for/solar-installation)
    - [General contractors](https://scalewithsearch.com/for/general-contractors-and-construction)
    - [Paving, concrete, and flooring contractors](https://scalewithsearch.com/for/paving)
  - Practices and professional services
    - [Bookkeeping and tax practices](https://scalewithsearch.com/for/bookkeeping-and-tax-practices)
    - [Dental practices](https://scalewithsearch.com/for/dental-practices)
    - [Family and criminal defense law firms](https://scalewithsearch.com/for/family-and-criminal-defense-law-firms)
    - [Med spas and aesthetics practices](https://scalewithsearch.com/for/med-spas-and-aesthetics)
    - [Personal injury law firms](https://scalewithsearch.com/for/personal-injury-law-firms)
    - [Veterinary clinics](https://scalewithsearch.com/for/veterinary-clinics)
    - [Gyms and fitness studios](https://scalewithsearch.com/for/fitness)
    - [Therapy and outpatient health practices](https://scalewithsearch.com/for/therapy-and-outpatient-health)
    - [Medical billing companies](https://scalewithsearch.com/for/medical-billing)
    - [Insurance agencies](https://scalewithsearch.com/for/insurance-agencies)
    - [Financial advisors](https://scalewithsearch.com/for/financial-advisors)
    - [Property management companies](https://scalewithsearch.com/for/property-management)
    - [Recruiting and staffing agencies](https://scalewithsearch.com/for/recruiting-and-staffing)
    - [Architects and interior designers](https://scalewithsearch.com/for/architects-and-interior-designers)
    - [Logistics and supply chain companies](https://scalewithsearch.com/for/logistics-and-supply-chain)
  - Agencies, MSPs, and manufacturing
    - [IT and managed service providers](https://scalewithsearch.com/for/it-and-managed-service-providers)
    - [Machine shops and precision manufacturers](https://scalewithsearch.com/for/machine-shops-and-precision-manufacturing)
    - [Marketing agencies and freelancers](https://scalewithsearch.com/for/marketing-agencies-and-freelancers)
    - [SEO agencies and consultants](https://scalewithsearch.com/for/seo-agencies-and-consultants)
    - [Small manufacturers and fabricators](https://scalewithsearch.com/for/small-manufacturers-and-fabricators)
  - Restaurants, shops, studios, and nonprofits
    - [Restaurants and hospitality businesses](https://scalewithsearch.com/for/restaurants-and-hospitality)
    - [Retail stores and ecommerce sellers](https://scalewithsearch.com/for/retail-and-ecommerce)
    - [Photographers, event planners, and travel agents](https://scalewithsearch.com/for/photographers)
    - [Churches and nonprofits](https://scalewithsearch.com/for/churches-and-nonprofits)
  - [All industries](https://scalewithsearch.com/for/)
- Learn
  - For your office
    - [Office job guides](https://scalewithsearch.com/guides/)
    - [Browser calculators](https://scalewithsearch.com/tools/)
  - Start here
    - [How it works](https://scalewithsearch.com/how-it-works)
    - [Free Starter Kit](https://scalewithsearch.com/kit/business-memory-starter-kit.zip)
    - [Synthetic specimen](https://scalewithsearch.com/specimen/working-session-specimen.zip)
  - Guides
    - [The Complete Guide to Business Memory for AI Agents](https://scalewithsearch.com/articles/business-memory-for-ai-agents-guide)
    - [The Complete Small-Business Guide to AI Agent Governance](https://scalewithsearch.com/articles/ai-agent-governance-guide-small-business)
    - [The Complete Guide to Leaving Vendor AI Memory](https://scalewithsearch.com/articles/leaving-vendor-ai-memory-guide)
  - Articles by cluster
    - [Business memory](https://scalewithsearch.com/articles/business-memory-for-ai-agents-guide)
    - [Agent governance](https://scalewithsearch.com/articles/ai-agent-governance-guide-small-business)
    - [Migration and ownership](https://scalewithsearch.com/articles/leaving-vendor-ai-memory-guide)
  - For machines
    - [llms.txt](https://scalewithsearch.com/llms.txt)
    - [llms-full.txt](https://scalewithsearch.com/llms-full.txt)
    - [Machine view](https://scalewithsearch.com/?view=machine)
- Company
  - Evidence
    - [Proof](https://scalewithsearch.com/proof)
  - Company
    - [About](https://scalewithsearch.com/about)

# Run Lighthouse in GitHub Actions to block SEO regressions before merge.

A developer refactors the page template. The pull request passes review. After deploy, the meta description is gone from every product page, and nobody notices for three weeks.

Lighthouse audits a page for performance, accessibility, SEO, and best practices. A manual Lighthouse run before each deploy depends on memory. GitHub Actions can run the same audit on every pull request and stop the merge when a check fails. This guide sets up that workflow, tunes it for SEO, and adds alerts.

## Know what automation fixes

Manual audits fail in three ways:

- **Inconsistency.** Developers forget the audit, audit only on desktop, or skip it under deadline.
- **Late detection.** A regression found after deploy means a rollback, broken pages for users, and lost rankings.
- **No history.** A one-time score shows no trend, so slow decline goes unseen.

An automated audit runs on every pull request. It catches the regression during code review, before the merge to `main`. A failed assertion blocks the merge. Stored results give you a trend line.

For SEO, the workflow catches these regressions:

- a removed title, meta description, or canonical tag;
- broken structured data;
- crawl problems, such as uncrawlable links or a changed `robots.txt`;
- Core Web Vitals trends across releases.

The same idea extends to other SEO checks in your pipeline. The [SEO testing guide for CI/CD pipelines](/articles/seo-testing-ci-cd-pipeline) covers checks that Lighthouse does not run.

## Create the basic workflow

Create the file `.github/workflows/lighthouse.yml`:

```yaml
name: Lighthouse CI

on:
  pull_request:
    branches:
      - main

jobs:
  lighthouse:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v7

      - name: Install Node.js
        uses: actions/setup-node@v7
        with:
          node-version: '24'

      - name: Install dependencies
        run: npm ci

      - name: Build site
        run: npm run build

      - name: Run Lighthouse
        uses: treosh/lighthouse-ci-action@v12
        with:
          urls: |
            https://example.com
            https://example.com/blog
            https://example.com/products
          uploadArtifacts: true
          temporaryPublicStorage: true
```

The workflow does five things, in order:

1. It starts on each pull request to `main`.
2. It checks out the code.
3. It installs dependencies and builds the site.
4. It runs Lighthouse against the listed URLs.
5. It uploads the reports as build artifacts.

The version tags in these samples match the current major releases as of September 2026. Node.js 20 reached end of life in April 2026, so the sample uses Node.js 24. Check each action's release page before you copy a tag.

Choose the URLs with care. Audit the homepage, the top landing pages, and one page of each key template. Five to ten pages catch most template regressions.

## Store history with Lighthouse CI Server

Artifacts expire. For history across branches and pull requests, run Lighthouse CI Server. It gives you four things:

- stored audit history for every branch and pull request;
- a web interface that compares runs;
- trend charts over time;
- assertions that fail a build when a score drops.

Set it up in three steps:

1. Deploy Lighthouse CI Server on a Node.js host with a persistent database. A Docker container on your own server works.
2. Point the workflow at the server.
3. Add assertions in `lighthouserc.json`.

```yaml
- name: Run Lighthouse CI
  uses: treosh/lighthouse-ci-action@v12
  with:
    urls: |
      https://example.com
      https://example.com/blog
    serverBaseUrl: https://lhci.example.com
    serverToken: ${{ secrets.LHCI_SERVER_TOKEN }}
```

```json
{
  "ci": {
    "collect": {
      "numberOfRuns": 3
    },
    "assert": {
      "assertions": {
        "categories:performance": ["error", {"minScore": 0.9}],
        "categories:seo": ["error", {"minScore": 0.95}],
        "categories:accessibility": ["warn", {"minScore": 0.9}]
      }
    },
    "upload": {
      "target": "lhci",
      "serverBaseUrl": "https://lhci.example.com"
    }
  }
}
```

These assertions require a performance score of 90 or more and an SEO score of 95 or more. An accessibility score under 90 produces a warning but does not fail the run. Keep the upload token in a GitHub secret, not in the file. Lighthouse CI reads it from the `LHCI_TOKEN` environment variable.

To block the merge on a failed assertion, make the Lighthouse job a required status check. Set it in the branch protection rule for `main`.

## Tune the SEO checks

The Lighthouse SEO category checks page basics. As of Lighthouse 13 (September 2026), the automated audits have these IDs:

| Audit ID | What it checks |
|---|---|
| `document-title` | The page has a non-empty `title` element |
| `meta-description` | The page has a meta description |
| `http-status-code` | The page returns a successful status code |
| `is-crawlable` | No `noindex` or `robots.txt` rule blocks the page |
| `robots-txt` | The `robots.txt` file is valid |
| `crawlable-anchors` | Links use `a href`, not only JavaScript click handlers |
| `link-text` | Links have descriptive text, not "click here" |
| `image-alt` | Images have `alt` attributes |
| `hreflang` | The `hreflang` annotations are valid |
| `canonical` | The canonical link is valid |

The audit list changes between Lighthouse versions. Earlier versions also checked font size and tap-target size for mobile. Run `lighthouse --list-all-audits` to print the list for your version.

Decide which failures block a merge. Add per-audit assertions to `lighthouserc.json`:

```json
{
  "ci": {
    "assert": {
      "assertions": {
        "categories:seo": ["error", {"minScore": 0.95}],
        "document-title": "error",
        "meta-description": "error",
        "link-text": "warn",
        "crawlable-anchors": "error",
        "image-alt": "warn",
        "hreflang": "error",
        "canonical": "error"
      }
    }
  }
}
```

With this file, a missing title or meta description blocks the merge. So do an invalid canonical, an invalid `hreflang`, and an uncrawlable link. Generic link text and a missing `alt` attribute produce warnings only. For the canonical rules the audit enforces, read the [canonical tags guide for developers](/articles/canonical-tags-developers).

### Validate structured data in a separate step

Lighthouse lists "Structured data is valid" as a manual check. It does not validate your schema. Add a separate step:

```yaml
- name: Validate Structured Data
  run: |
    npx structured-data-testing-tool https://example.com
```

Google's Rich Results Test stays a manual check, because it offers no public API. Use it on each template after a structured data change. The [structured data implementation guide](/articles/structured-data-implementation) covers the markup itself.

## Track Core Web Vitals

Lighthouse measures Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS) in the lab. It cannot measure Interaction to Next Paint (INP) in a page-load audit, because INP needs real user input. Total Blocking Time (TBT) is the lab proxy. INP replaced First Input Delay (FID) as a Core Web Vital in March 2024, so TBT now stands in for INP.

Set thresholds in `lighthouserc.json`:

```json
{
  "ci": {
    "assert": {
      "assertions": {
        "largest-contentful-paint": ["error", {"maxNumericValue": 2500}],
        "cumulative-layout-shift": ["error", {"maxNumericValue": 0.1}],
        "total-blocking-time": ["error", {"maxNumericValue": 200}]
      }
    }
  }
}
```

| Metric | Good | Needs improvement | Poor |
|---|---|---|---|
| LCP | 2.5 s or less | 2.5 s to 4.0 s | Over 4.0 s |
| CLS | 0.1 or less | 0.1 to 0.25 | Over 0.25 |
| TBT (lab proxy for INP) | 200 ms or less | 200 ms to 600 ms | Over 600 ms |

A pull request that exceeds a threshold fails. The developer fixes the regression before the merge. To set these numbers per page type, use [performance budgets](/articles/performance-budgets-seo).

### Keep a trend line

Choose one of three stores for scores over time:

- **Lighthouse CI Server.** Trend charts are built in.
- **Your analytics platform.** Post each score from the workflow.
- **A spreadsheet.** Append each score with a script that calls the Google Sheets API.

The action exposes a `manifest` output with the summary scores. This step posts the performance score of the representative run:

```yaml
- name: Post Lighthouse results to analytics
  env:
    MANIFEST: ${{ steps.lhci.outputs.manifest }}
  run: |
    SCORE=$(echo "$MANIFEST" | jq '[.[] | select(.isRepresentativeRun)][0].summary.performance')
    curl -X POST https://analytics.example.com/lighthouse \
      -H "Content-Type: application/json" \
      -d "{\"score\": $SCORE, \"timestamp\": \"$(date -Iseconds)\"}"
```

## Audit preview and authenticated pages

Lighthouse needs a URL it can reach. Staging builds and pages behind a login need extra steps.

### Preview deployments

Deploy each pull request to a preview environment, such as Vercel or Netlify, and audit the preview URL.

```yaml
- name: Deploy to Vercel
  id: vercel
  uses: amondnet/vercel-action@v42
  with:
    vercel-token: ${{ secrets.VERCEL_TOKEN }}
    vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
    vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}

- name: Run Lighthouse on preview
  uses: treosh/lighthouse-ci-action@v12
  with:
    urls: ${{ steps.vercel.outputs.preview-url }}
```

### Pages behind a login

Lighthouse cannot pass a login screen by default. You have two options.

The first option is a CI bypass. Create a temporary token or bypass parameter that admits Lighthouse during CI runs. Restrict it to your CI runners.

The second option is a scripted login with Puppeteer. Log in first, then pass the same page to Lighthouse. Lighthouse 10 and later ship as an ES module.

```javascript
import puppeteer from 'puppeteer';
import lighthouse from 'lighthouse';

const browser = await puppeteer.launch();
const page = await browser.newPage();

// Log in with a test account. Read credentials from CI secrets.
await page.goto('https://example.com/login');
await page.type('#username', process.env.TEST_USER);
await page.type('#password', process.env.TEST_PASSWORD);
await page.click('#login-button');
await page.waitForNavigation();

// Audit with the logged-in session.
const result = await lighthouse(
  'https://example.com/dashboard',
  { output: 'json', disableStorageReset: true },
  undefined,
  page
);

console.log(result.lhr.categories.seo.score);
await browser.close();
```

Use a test account with no access to real customer data.

## Alert the team on a failure

A failed check is useful only when someone sees it. Use one or more of three channels.

**Slack.** Post to a channel through an incoming webhook:

```yaml
- name: Notify Slack on failure
  if: failure()
  uses: slackapi/slack-github-action@v4
  with:
    webhook: ${{ secrets.SLACK_WEBHOOK }}
    webhook-type: incoming-webhook
    payload: |
      {
        "text": "Lighthouse audit failed on PR #${{ github.event.pull_request.number }}: ${{ github.event.pull_request.html_url }}"
      }
```

**Email.** GitHub sends email for failed workflow runs to the person who triggered them. Set it under your notification settings, or add an email action for a shared inbox.

**Pull request comment.** Post the scores where the reviewer already looks. The full workflow below shows this step.

## Use the full workflow

This workflow builds the site, serves it on `localhost`, audits three pages, comments the scores, and alerts Slack on failure.

```yaml
name: Lighthouse CI

on:
  pull_request:
    branches:
      - main

jobs:
  lighthouse:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v7

      - name: Setup Node.js
        uses: actions/setup-node@v7
        with:
          node-version: '24'

      - name: Install dependencies
        run: npm ci

      - name: Build site
        run: npm run build

      - name: Start server
        run: |
          npm run start &
          npx wait-on http://localhost:3000

      - name: Run Lighthouse CI
        id: lhci
        uses: treosh/lighthouse-ci-action@v12
        with:
          urls: |
            http://localhost:3000
            http://localhost:3000/blog
            http://localhost:3000/products
          uploadArtifacts: true
          configPath: './lighthouserc.json'

      - name: Comment results on PR
        if: always()
        uses: actions/github-script@v9
        env:
          MANIFEST: ${{ steps.lhci.outputs.manifest }}
        with:
          script: |
            const runs = JSON.parse(process.env.MANIFEST || '[]')
              .filter(r => r.isRepresentativeRun);
            const lines = runs.map(r =>
              `- ${r.url}: SEO ${Math.round(r.summary.seo * 100)}, Performance ${Math.round(r.summary.performance * 100)}`);
            await github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `Lighthouse results:\n${lines.join('\n')}`
            });

      - name: Notify Slack on failure
        if: failure()
        uses: slackapi/slack-github-action@v4
        with:
          webhook: ${{ secrets.SLACK_WEBHOOK }}
          webhook-type: incoming-webhook
          payload: |
            {
              "text": "Lighthouse audit failed for PR #${{ github.event.pull_request.number }}"
            }
```

A server-rendered app works the same way. Build it, start it, and audit the local URL.

## Reduce noise and widen coverage

**Flaky scores.** Performance scores vary between runs on shared CI machines. Set `numberOfRuns: 3` in `lighthouserc.json`. Lighthouse CI then runs three audits per URL and uses the median run.

**Mobile and desktop.** Lighthouse emulates a mobile device by default. For a desktop run, use a second config file with the desktop preset, and run both through a matrix build:

```json
{
  "ci": {
    "collect": {
      "settings": {
        "preset": "desktop"
      }
    }
  }
}
```

**Third-party scripts.** Lighthouse audits the whole page, third-party scripts included. If a vendor script fails an audit, you have three options. Fix it with the vendor, remove the script, or change that assertion from `error` to `warn`.

**Triggers.** An audit on every commit uses more CI minutes. To audit each merge to `main` as well, add `push: branches: [main]` to the `on` block. Most teams audit pull requests only.

**Competitors.** Lighthouse audits any public URL. Add competitor pages to the `urls` list to track your scores against theirs. Treat those numbers as a lab comparison, not as their field data.

When a check fails and the cause is not obvious, the [Core Web Vitals debugging guide](/articles/core-web-vitals-debugging) walks through the trace.

----

```text
                  .|########||.                                       .|########||.                                       .|########||.
               |##||.      .||##|.                                 |##||.      .||##|.                                 |##||.      .||##|.
             |#|.              .|#|.                             |#|.              .|#|.                             |#|.              .|#|.
           |#|                    |#|                          |#|                    |#|                          |#|                    |#|
         .#|                        |#.                      .#|                        |#.                      .#|                        |#.
        .#.                          .#|                    .#.                          .#|                    .#.                          .#|
       |#.                            .#|                  |#.                            .#|                  |#.                            .#|
      |#             ......             #|                |#             ......             #|                |#             ......             #|
     .#           ||#########|           #|              .#           ||#########|           #|              .#           ||#########|           #|
    .#.         |######||######|.        .#.            .#.         |######||######|.        .#.            .#.         |######||######|.        .#.
    #.        .##|###|##|#|######|        .#            #.        .##|###|##|#|######|        .#            #.        .##|###|##|#|######|        .#
   ||        |##|#||||||||||||#||#|        ||          ||        |##|#||||||||||||#||#|        ||          ||        |##|#||||||||||||#||#|        ||
   #        |#||||||||||||||||||||#|        #.         #        |#||||||||||||||||||||#|        #.         #        |#||||||||||||||||||||#|        #.
  ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||
  #       .#||||||||||||||||||||||||#|       #        #       .#||||||||||||||||||||||||#|       #        #       .#||||||||||||||||||||||||#|       #
 ||   ....|||#||||||##|#|||#|#||##||||....|. ||      ||   ....|||#||||||##|#|||#|#||##||||....|. ||      ||   ....|||#||||||##|#|||#|#||##||||....|. ||
 #.  .  ....|#  ....#|||   ||| .#|||  ....#. .#      #.  .  ....|#  ....#|||   ||| .#|||  ....#. .#      #.  .  ....|#  ....#|||   ||| .#|||  ....#. .#
 #   .  ||||#| .#####||  . .#| .#|||  ||||#   #.     #   .  ||||#| .#####||  . .#| .#|||  ||||#   #.     #   .  ||||#| .#####||  . .#| .#|||  ||||#   #.
.|   |||||  #. |#|||||. ||  #. |#||. .|||||   ||    .|   |||||  #. |#|||||. ||  #. |#||. .|||||   ||    .|   |||||  #. |#|||||. ||  #. |#||. .|||||   ||
||   |....  #. ....|#.      |. ...|. ....||   ||    ||   |....  #. ....|#.      |. ...|. ....||   ||    ||   |....  #. ....|#.      |. ...|. ....||   ||
#.  .||||||##||||||##||####|||||||#||||||#|   .#    #.  .||||||##||||||##||####|||||||#||||||#|   .#    #.  .||||||##||||||##||####|||||||#||||||#|   .#
#    .||####|###########################|.     #    #    .||####|###########################|.     #    #    .||####|###########################|.     #
#      .#||||||.#.|| # |. ..# #| #|||||#|      #    #      .#||||||.#.|| # |. ..# #| #|||||#|      #    #      .#||||||.#.|| # |. ..# #| #|||||#|      #
#      .#|||||| ..  |# ## |#| ...#|#|||#|      #    #      .#|||||| ..  |# ## |#| ...#|#|||#|      #    #      .#|||||| ..  |# ## |#| ...#|#|||#|      #
#      .#|||#|# .# .#| #| ##|.#..#|||||#|      #    #      .#|||#|# .# .#| #| ##|.#..#|||||#|      #    #      .#|||#|# .# .#| #| ##|.#..#|||||#|      #
#      .#||||||############|######|||||#|      #    #      .#||||||############|######|||||#|      #    #      .#||||||############|######|||||#|      #
#   |...||#||||||#||||#|#||||||#|||||#||| |.|  #    #   |...||#||||||#||||#|#||||||#|||||#||| |.|  #    #   |...||#||||||#||||#|#||||||#|||||#||| |.|  #
#. .. ||||# .|||##|.  |#| .|| || .|||#. #|  # .#    #. .. ||||# .|||##|.  |#| .|| || .|||#. #|  # .#    #. .. ||||# .|||##|.  |#| .|| || .|||#. #|  # .#
|| |  ...||  ...##| |  #| .|. |. #####  .. .| ||    || |  ...||  ...##| |  #| .|. |. #####  .. .| ||    || |  ...||  ...##| |  #| .|. |. #####  .. .| ||
|| ||||| || ||||#|  .  |. |. |#. ||||| |#| || ||    || ||||| || ||||#|  .  |. |. |#. ||||| |#| || ||    || ||||| || ||||#|  .  |. |. |#. ||||| |#| || ||
.# |.....#|....|#.||||.|||##.|#|....||.#||.#. #.    .# |.....#|....|#.||||.|||##.|#|....||.#||.#. #.    .# |.....#|....|#.||||.|||##.|#|....||.#||.#. #.
 #.|||||||#############################| ||| .#      #.|||||||#############################| ||| .#      #.|||||||#############################| ||| .#
 ||       ##||#||#||||||#||#||#||#||##.      ||      ||       ##||#||#||||||#||#||#||#||##.      ||      ||       ##||#||#||||||#||#||#||#||##.      ||
  #       .#|||||||||#||#|||||||||||#|       #        #       .#|||||||||#||#|||||||||||#|       #        #       .#|||||||||#||#|||||||||||#|       #
  ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||        ||       |#||||||||||||||||||||||#|       ||
  .#        |#||||||||||||||||||||#|        #.        .#        |#||||||||||||||||||||#|        #.        .#        |#||||||||||||||||||||#|        #.
   ||        |#||||||||||||||||||#|        ||          ||        |#||||||||||||||||||#|        ||          ||        |#||||||||||||||||||#|        ||
    #.        .######|#|#########|        .#            #.        .######|#|#########|        .#            #.        .######|#|#########|        .#
    .#.         |#####||||#####|         .#.            .#.         |#####||||#####|         .#.            .#.         |#####||||#####|         .#.
     |#           ||########||           #.              |#           ||########||           #.              |#           ||########||           #.
      |#             ......             #|                |#             ......             #|                |#             ......             #|
       |#.                            .#|                  |#.                            .#|                  |#.                            .#|
        |#.                          .#.                    |#.                          .#.                    |#.                          .#.
         .#|                        |#.                      .#|                        |#.                      .#|                        |#.
           |#|                    |#|                          |#|                    |#|                          |#|                    |#|
            .|#|.              .|#|.                            .|#|.              .|#|.                            .|#|.              .|#|.
               |##||.      .||##|                                  |##||.      .||##|                                  |##||.      .||##|
                 .||########||.                                      .||########||.                                      .||########||.

Scale With Search  2026  [scalewithsearch.com](https://scalewithsearch.com)
```
