Skip to content

Audit SEO automatically with Lighthouse CI - #107

Merged
ultimatecoder merged 1 commit into
masterfrom
feat/lighthouse-seo-ci
Aug 6, 2026
Merged

Audit SEO automatically with Lighthouse CI#107
ultimatecoder merged 1 commit into
masterfrom
feat/lighthouse-seo-ci

Conversation

@ultimatecoder

Copy link
Copy Markdown
Owner

What #35 actually asked for

[ ] Find a way to automatically test SEO appropriateness using any open source tools
[ ] Identify and list automated SEO check service
[ ] Configure tools / services to run periodically on your tool
[ ] Improve existing code according to improvements suggested by the tool

Three of the four sub-tasks are about tooling, and only the last is about changing code — and it is explicitly downstream of what the tool reports. So the tool comes first here, and the code changes are whatever it flagged.

The tool

Lighthouse via @lhci/cli, both open source. .lighthouserc.json runs its SEO category against seven representative pages — homepage, about, tag index, one tag page, two posts, and a post under the book/review categories — and asserts a perfect score.

A new SEO audit workflow runs it on every pull request and on a weekly cron (Mondays 06:00 UTC), satisfying "run periodically" — search engines change what they reward without any commit on our side. Reports upload as an artifact for 30 days.

Runtime is about 90 seconds.

Three things setting this up revealed

The audit must build the way pages.yml does. A development build has no site.url, which leaves rel=canonical relative and robots.txt missing its sitemap line. Lighthouse scored those pages 0.83 while production scored 100 — a pure false alarm. The workflow builds with JEKYLL_ENV=production and the production config.

Autodiscovery silently skipped every post. Pointed at _site, lhci collects index.html files only. It happily audited 25 URLs — all tag indexes, homepage, about, 404 — and zero of the twelve posts, which are exactly the pages whose SEO matters. URLs are now listed explicitly.

Listing post URLs required pinning the timezone. Jekyll derives permalinks from the post date in local time, so 2019-01-13 01:23:12 +0530 builds to /2019/01/12/ on a UTC runner but /2019/01/13/ on a machine set to IST. The same commit produced different URLs depending on where it was built. timezone: UTC makes local builds agree with CI.

All twelve live post URLs were checked against the deployed site before and after — every one returns 200 and none of them change. This matches current production behaviour rather than altering it.

What the tool then reported

Two links whose text does not describe their target:

Page Link text Target
Python 3.7 walkthrough this docs.python.org changelog
Introduction to the Command Line here FLOSS Manuals editor

The second was only found because posts got added to the audit list — autodiscovery would have missed it entirely.

Both reworded. Every audited page now scores 100.

Verification

$ npx @lhci/cli@0.14.x autorun --config=.lighthouserc.json
Checking assertions against 7 URL(s), 7 total run(s)
All results processed!
Done running autorun.

./scripts/test (build + htmlproofer) also passes.

Note

Two <title> and two <meta name="description"> tags per page — _includes/head.html hand-rolls what {% seo %} already emits — is a real defect, but Lighthouse does not flag it (document-title only checks a title exists). It is not tool-reported, so it is deliberately not in this PR and will get its own change.

Closes #35

🤖 Generated with Claude Code

Issue #35 asks for an open source tool that tests SEO appropriateness, for
that tool to run periodically, and only then for the code to be improved
according to what it reports. This does the first three and acts on the
findings of the fourth.

Lighthouse is the tool. `.lighthouserc.json` runs its SEO category against
seven representative pages — the homepage, about, the tag index, one tag
page, two posts and a post under the book/review categories — and asserts a
perfect category score. A new workflow runs it on every pull request and on
a weekly cron, since search engines change what they reward without any
commit on our side.

Three things this turned up while being set up.

The audit has to build the way pages.yml does. A development build has no
`site.url`, which leaves `rel=canonical` relative and robots.txt without a
sitemap line; Lighthouse scored those pages 0.83 while production scored
100. The workflow therefore builds with the production config.

Autodiscovery is not enough. Pointed at `_site` it collects `index.html`
files only, so all twelve posts — the pages whose SEO actually matters —
went unaudited. The URLs are listed explicitly instead.

Listing post URLs meant pinning the timezone. Jekyll derives permalinks
from the post date in local time, so `2019-01-13 01:23:12 +0530` builds to
/2019/01/12/ on a UTC runner and /2019/01/13/ on a machine in IST. The same
commit produced different URLs depending on where it was built. Setting
`timezone: UTC` makes local builds agree with CI; all twelve live post URLs
were checked against the deployed site and none of them change.

The audit then reported two links whose text does not describe the target,
"this" and "here". Both are reworded, which brings every audited page to
100.

Closes #35

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ultimatecoder
ultimatecoder merged commit b21301a into master Aug 6, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Identify SEO issues

1 participant