feat: free Lighthouse audits via PageSpeed Insights when PAGESPEED_API_KEY is set#52
feat: free Lighthouse audits via PageSpeed Insights when PAGESPEED_API_KEY is set#52mattmacrocket wants to merge 2 commits into
Conversation
bensenescu
left a comment
There was a problem hiding this comment.
Could you add a script which exercises this new logic that I can easily test? When I tried to test this, it didn't work and everything timed out:
"code": 500,
"message": "Lighthouse returned error: Something went wrong.",
"errors": [
{
"message": "Lighthouse returned error: Something went wrong.",
Lighthouse attempt 1 failed for https://openseo.so/docs/skills: PageSpeed Insights HTTP 500: {
"error": {
"code": 500,
"message": "Lighthouse returned error: Something went wrong.",
"errors": [
{
"message": "Lighthouse returned error: Something went wrong.",
Lighthouse attempt 1 failed for https://openseo.so/: The operation was aborted due to timeout
Lighthouse attempt 1 failed for https://openseo.so/docs/skills: The operation was aborted due to timeout
Lighthouse attempt 1 failed for https://openseo.so/docs/skills/competitor-analysis: The operation was aborted due to timeout
Lighthouse attempt 1 failed for https://openseo.so/docs/skills/competitor-analysis: The operation was aborted due to timeout
Lighthouse attempt 2 failed for https://openseo.so/: PageSpeed Insights HTTP 500: {
"error": {
"code": 500,
"message": "Lighthouse returned error: Something went wrong.",
"errors": [
{
"message": "Lighthouse returned error: Something went wrong.",
Lighthouse attempt 2 failed for https://openseo.so/docs/skills/competitor-analysis: PageSpeed Insights HTTP 500: {
"error": {
"code": 500,
"message": "Lighthouse returned error: Something went wrong.",
"errors": [
{
"message": "Lighthouse returned error: Something went wrong.",
Lighthouse attempt 3 failed for https://openseo.so/docs/skills/competitor-analysis: PageSpeed Insights HTTP 500: {
"error": {
"code": 500,
"message": "Lighthouse returned error: Something went wrong.",
"errors": [
{
"message": "Lighthouse returned error: Something went wrong.",
Lighthouse failed after 3 attempts for https://openseo.so/docs/skills/competitor-analysis: PageSpeed Insights HTTP 500: {
"error": {
"code": 500,
"message": "Lighthouse returned error: Something went wrong.",
"errors": [
{
"message": "Lighthouse returned error: Something went wrong.",
Lighthouse attempt 2 failed for https://openseo.so/docs/skills: The operation was aborted due to timeout
Lighthouse attempt 3 failed for https://openseo.so/docs/skills: PageSpeed Insights HTTP 500: {
"error": {
"code": 500,
"message": "Lighthouse returned error: Something went wrong.",
"errors": [
{
"message": "Lighthouse returned error: Something went wrong.",
Lighthouse failed after 3 attempts for https://openseo.so/docs/skills: PageSpeed Insights HTTP 500: {
"error": {
"code": 500,
"message": "Lighthouse returned error: Something went wrong.",
"errors": [
{
"message": "Lighthouse returned error: Something went wrong.",
| url: "", | ||
| maxPagesInput: "50", | ||
| runLighthouse: false, | ||
| // On by default: without Lighthouse the results view has no Performance tab |
There was a problem hiding this comment.
Let's keep this false as this will still cost people money who haven't set up the key?
There was a problem hiding this comment.
Done, reverted to false. Agreed: without the key this would have pushed everyone onto the metered path by default.
| We choose a sample of 20 pages to audit, removing pages from | ||
| duplicate templates. | ||
| </p> | ||
| <p className="text-xs text-base-content/60"> |
There was a problem hiding this comment.
Let's remove this copy to keep things simple
…I_KEY is set Site-audit Lighthouse currently runs on the metered DataForSEO OnPage endpoint ($0.00425/page) even though Google's PageSpeed Insights API returns the same Lighthouse report for free (~25k requests/day with a free API key). - Add src/server/lib/pagespeedLighthousePayload.ts: fetches PSI and normalizes the report into the exact same StoredLighthousePayload the DataForSEO path produces, so R2 payloads, scores, metrics, and the issue-details view are provider-agnostic. Handles Lighthouse 13.x returning details.items as an object for some audits, and a 90s timeout for slow runs. - Route the audit Lighthouse phase to PSI only when PAGESPEED_API_KEY is set, falling back to the existing DataForSEO path otherwise, so current deployments keep their behavior with zero action. (Keyless PSI is not viable: the anonymous shared quota returns HTTP 429 almost always.) - Widen the stored-payload source enum to accept both providers; existing stored DataForSEO payloads still parse. - Default "Include Lighthouse" to on. Without Lighthouse the results view has no Performance tab and the only recovery is re-crawling the whole site. - Plumb PAGESPEED_API_KEY through .env.example, compose.yaml, env.d.ts, and document it in docs/SELF_HOSTING_DOCKER.md. Verified end to end on a live 10-page audit: 8/8 Lighthouse runs via PSI (mobile + desktop), scores and per-page issue details render unchanged, and no DataForSEO credits are spent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…eck script Addresses the review on every-app#52: - Root cause of the timeouts/500s: the audit's Lighthouse batch fires up to 10 URLs x 2 strategies at PSI simultaneously, and PSI's Lighthouse backend rejects parallel bursts (HTTP 500 'Lighthouse returned error') and queues the rest past the request timeout. Measured live: 20 concurrent runs fail ~10% instantly; 4 concurrent completes 20/20. All PSI calls now go through a small in-module queue (4 at a time, queue wait does not consume the request timeout) and the per-request timeout is raised to 120s (successful runs under load measured at 60-90s). - runLighthouse defaults back to false (no surprise spend for anyone without the free key), and the extra checkbox copy is removed. - New scripts/pagespeed-lighthouse-check.ts (pnpm pagespeed:check): exercises the exact audit code path (same module, same queue, same retry shape) against any URLs. Verified 6/6 against the URLs from the review. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
f093f05 to
65f7225
Compare
…eck script Addresses the review on every-app#52: - Root cause of the timeouts/500s: the audit's Lighthouse batch fires up to 10 URLs x 2 strategies at PSI simultaneously, and PSI's Lighthouse backend rejects parallel bursts (HTTP 500 'Lighthouse returned error') and queues the rest past the request timeout. Measured live: 20 concurrent runs fail ~10% instantly; 4 concurrent completes 20/20. All PSI calls now go through a small in-module queue (4 at a time, queue wait does not consume the request timeout) and the per-request timeout is raised to 120s (successful runs under load measured at 60-90s). - runLighthouse defaults back to false (no surprise spend for anyone without the free key), and the extra checkbox copy is removed. - New scripts/pagespeed-lighthouse-check.ts (pnpm pagespeed:check): exercises the exact audit code path (same module, same queue, same retry shape) against any URLs. Verified 6/6 against the URLs from the review. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
65f7225 to
1d7cd3a
Compare
|
Thanks for the test run, that log was exactly what I needed to reproduce it. Root cause: the audit's Lighthouse phase fires batches of up to 10 URLs x 2 strategies at PSI simultaneously, and PSI's Lighthouse backend rejects parallel bursts with that exact HTTP 500 ("Lighthouse returned error: Something went wrong.") while queueing the rest past the request timeout. Reproduced against openseo.so: 20 concurrent runs fail ~10% instantly with the 500; 4 concurrent completes 20/20. Fixed in the new commit:
Test script (reads pnpm pagespeed:check --url=https://openseo.so/,https://openseo.so/docs/skills,https://openseo.so/docs/skills/competitor-analysisIt exercises the exact audit code path (same module, same queue, same 3-attempt retry shape). Sample run against the URLs from your log:
Also rebased on current main, and the PR description is updated to match (default stays off). 🤖 Generated with Claude Code |
What
Site-audit Lighthouse currently runs on the metered DataForSEO OnPage endpoint ($0.00425/page) even though Google's PageSpeed Insights API returns the same Lighthouse report for free (roughly 25k requests/day with a free API key). This PR routes the audit's Lighthouse phase to PSI when a
PAGESPEED_API_KEYis set, and falls back to the existing DataForSEO path otherwise, so current deployments keep their exact behavior with zero action.src/server/lib/pagespeedLighthousePayload.ts: fetches PSI and normalizes the report into the exact sameStoredLighthousePayloadthe DataForSEO path produces. R2 payloads, scores, metrics, and the issue-details view are provider-agnostic; the stored-payloadsourceenum accepts both providers and existing stored payloads still parse.details.itemscomes back as an object (not array) for some audits (e.g.document-latency-insight), which would otherwise fail the whole parse.PAGESPEED_API_KEYthrough.env.example,compose.yaml,env.d.ts, and documents it indocs/SELF_HOSTING_DOCKER.md.Why opt-in via key rather than always PSI
Keyless PSI requests share a tiny anonymous global quota that is almost always exhausted (HTTP 429 in practice), so PSI is only reliable with a key. Gating on the key means: self-hosters get free audits with a 2-minute free key, and deployments that do nothing (including hosted) are completely unaffected.
Notes for review
PAGESPEED_API_KEYon the hosted deployment would make audit Lighthouse free there too (no DataForSEO OnPage spend, no user credit metering on that path). Without the key, hosted behavior is unchanged.client.lighthouse.liveanddataforseoLighthousePayload.tscould be removed in a follow-up.Verification
tsc --noEmit,oxlint --type-aware,prettier --check,knip, and the full vitest suite (408 tests) pass.🤖 Generated with Claude Code
Follow-up (review round 1)
runLighthousedefaults back to false and the extra checkbox copy is removed, per the inline comments.pnpm pagespeed:check --url=https://openseo.so/,https://openseo.so/docs/skillsexercises the exact audit code path (same module, queue, and 3-attempt retry shape). ReadsPAGESPEED_API_KEYfrom.env.local.--attempts=1shows raw single-shot behavior,--strategy=and--sequential=truealso available. Verified 6/6 against the URLs from your review log.Greptile Summary
This PR adds an opt-in PageSpeed Insights path for site-audit Lighthouse runs. The main changes are:
PAGESPEED_API_KEYis configured.pagespeed:checkscript for local verification.Confidence Score: 5/5
Safe to merge with low risk.
The PSI path is opt-in, validates responses with
zod, reuses the existing payload builders, and preserves the DataForSEO fallback when the key is absent.No files require special attention.
What T-Rex did
Important Files Changed
PAGESPEED_API_KEYthrough the Docker Compose service environment.Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant Audit as Site audit Lighthouse phase participant Env as Runtime env participant PSI as PageSpeed Insights participant DFS as DataForSEO Lighthouse participant R2 as R2 payload storage Audit->>Env: read PAGESPEED_API_KEY alt key is configured Audit->>PSI: fetch Lighthouse report (queued, retryable) PSI-->>Audit: lighthouseResult Audit->>Audit: normalize to StoredLighthousePayload else key is absent Audit->>DFS: lighthouse.live(url, strategy) DFS-->>Audit: StoredLighthousePayload end Audit->>R2: store provider-neutral payload JSON R2-->>Audit: r2Key and payload size%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant Audit as Site audit Lighthouse phase participant Env as Runtime env participant PSI as PageSpeed Insights participant DFS as DataForSEO Lighthouse participant R2 as R2 payload storage Audit->>Env: read PAGESPEED_API_KEY alt key is configured Audit->>PSI: fetch Lighthouse report (queued, retryable) PSI-->>Audit: lighthouseResult Audit->>Audit: normalize to StoredLighthousePayload else key is absent Audit->>DFS: lighthouse.live(url, strategy) DFS-->>Audit: StoredLighthousePayload end Audit->>R2: store provider-neutral payload JSON R2-->>Audit: r2Key and payload sizeReviews (1): Last reviewed commit: "review: cap PSI concurrency, keep Lighth..." | Re-trigger Greptile