Repository navigation
fix(seo): resolve the in-repo Ahrefs September 2026 site-audit errors - #3716
Conversation
Three langfuse.com images exceeded the 1 MB image-size threshold in the Ahrefs Site Audit, and in each case the full-resolution file was reaching the browser. - The customer-story carousel passed `unoptimized` to next/image, so visitors downloaded the raw 1.4-2.4 MB PNGs. Dropping the prop lets Next serve WebP/AVIF at the width `sizes` already declares. (`images.unoptimized` is still set globally for STATIC_EXPORT builds.) - score-analytics-full-dashboard.png was a 5284px-wide screenshot with an unused alpha channel; resampled to 2048px, 3.78 MB -> 0.69 MB. - find-us.png was a satellite photo stored as PNG; converted to a 1920px progressive JPEG, 6.85 MB -> 0.58 MB. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@claude review |
There was a problem hiding this comment.
Claude Code Review
No review was started: this request came from a bot account. Manual reviews can only be requested by someone with write access to this repository. Ask a maintainer to comment @claude review, or have your automation post the comment from a user account with write access.
Tip: disable this comment in your organization's Code Review settings.
There was a problem hiding this comment.
Looks good, straightforward asset/config fix.
What was reviewed: the unoptimized prop removal in CustomerScreenshotCarousel.tsx (confirmed next.config.mjs still forces unoptimized: true for STATIC_EXPORT builds, so static export is unaffected); the find-us.mdx image path update to the new .jpg; and visually rendered both replaced binaries (find-us.jpg, score-analytics-full-dashboard.png) to confirm no quality/content regression. No md-override/ file exists for /find-us, so no override sync was needed.
Extended reasoning...
Overview
The diff touches five files: a one-line prop removal in components/customers/CustomerScreenshotCarousel.tsx, a one-line image path swap in content/marketing/find-us.mdx, and three binary asset changes (delete find-us.png, add find-us.jpg, replace score-analytics-full-dashboard.png with a smaller re-encode). This is purely an image-optimization/SEO fix with no logic or prose changes.
Security risks
None. No auth, crypto, permissions, or user input handling is touched. The only behavioral change is that carousel images now go through Next.js's built-in image optimizer instead of being served raw, which is a well-established, safe code path.
Level of scrutiny
Low. This is a small, mechanical, self-contained change (drop a prop, swap a filename, replace two binary assets). I verified the specific claim that removing unoptimized doesn't break the static-export build by checking next.config.mjs, which independently forces unoptimized: true when STATIC_EXPORT=true — so the PR's reasoning holds. I also visually rendered both new/changed images to confirm they display correctly and match their intended content (aerial map, dashboard screenshot) with no visible corruption or quality loss.
Other factors
No md-override/ file exists for /find-us, so the "keep overrides synchronized" rule doesn't apply here. The find-us.png reference is fully removed from source (grep confirms no remaining references outside the gitignored public/md-src/ build artifact). This is the kind of change that doesn't need a human to look closely before merging.
…ages `/japan` and the `/academy/japan/*` tree serve Japanese content and carry a self-referencing `ja-JP` hreflang, but the document reported `lang="en"`. Besides the Ahrefs "Hreflang and HTML lang mismatch" error on 15 URLs, that misreports the content language to screen readers and browser translation. Next.js only lets the root layout render `<html>`, and its attributes are serialized before any child renders, so one root layout cannot vary `lang` by route -- a nested layout that renders `<html lang="ja">` emits a second `<html>` tag rather than setting the attribute. Splitting the app into per-language root layouts would work but restructures every route, so instead the two Japanese layouts mount `DocumentLanguage`, which sets the attribute from an inline script while the document is still parsing and restores the site default when the reader navigates back out through client-side routing. The Japanese paths also serve `Content-Language: ja`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Monthly Ahrefs Site Audit triage for langfuse.com (project "Langfuse (Subdomains)", crawl 2026-09-03, health score 98, 86 URLs with errors).
Fixes the two Error-importance issues whose root cause is in this repo: Image file size too large (6 URLs) and Hreflang and HTML lang mismatch (15 URLs). The remaining 71 error URLs sit on subdomains built from other repos — see "Intentionally out of scope".
1. Oversized images
/images/customers/slite/slite-agent-enterprise-search.png(2.22 MB)CustomerScreenshotCarouselpassedunoptimizedtonext/image, so the raw PNG went to the browser/images/customers/slite/slite-agent-triage.png(2.38 MB)/images/customers/ravenna/ravenna-skill-builder.png(1.41 MB)/images/customers/ravenna/ravenna-ticket-list.png(1.59 MB)/images/docs/score-analytics-full-dashboard.png(3.78 MB)<img>incontent/docs/evaluation/overview.mdx_next/image?url=/images/find-us.png&w=3840(2.44 MB)find-us.jpg, 0.58 MB) and repointedcontent/marketing/find-us.mdxunoptimizedhas been on the carousel since it was introduced in #3378 and nothing depends on it.next.config.mjsalready setsimages.unoptimized: trueforSTATIC_EXPORT=true, so the static export is unaffected. This is a real page-weight win on/users/sliteand/users/ravenna, not only an audit checkbox.2. Hreflang and HTML lang mismatch
/japanand the 14/academy/japan/*pages serve Japanese content and declare a self-referencingja-JPhreflang, but the document reportedlang="en". Beyond the audit error, that misreports the content language to screen readers and browser translation.Why not a nested
<html lang="ja">: Next.js only lets the root layout render<html>, and its attributes are serialized before any child renders. Verified empirically against the dev server — a nested layout rendering<html lang="ja">emits a second<html>tag rather than setting the attribute:Why not per-language root layouts: that is what #3687 did, and it moves every route in
app/into a route group. It was closed unmerged, so this PR does not re-propose it.What this does instead:
components/DocumentLanguage.tsx, mounted by the two existing Japanese layouts (app/japan/layout.tsx,app/academy/japan/layout.tsx). It setsdocument.documentElement.langfrom an inline script that runs while the browser is still parsing the document — before first paint — and an effect restores"en"when the reader navigates back out through client-side routing.<html>already carriessuppressHydrationWarning, so mutating the attribute does not trip React. Thescript-srcCSP already allows'unsafe-inline'. No route or folder moves.The Japanese paths also serve a
Content-Language: jaresponse header, added innext.config.mjs.Known limitation, stated plainly: the HTML source still ships
lang="en"; only the live DOM carrieslang="ja". Google renders JavaScript so it sees the corrected value, but whether the Ahrefs check clears depends on whether its crawler reads the rendered DOM or the raw response. If it stays flagged after the next crawl, the only remaining fix is the per-language root layouts from #3687.Verification
Dev server (
pnpm dev, port 3333) and a production build.Build —
npx next build(prebuild skipped; it needs a GitHub token):✓ Compiled successfully in 67s,✓ Generating static pages (962/962), no errors. Reverted thenext-env.d.tsthe build dirtied.Document language:
Content-Languagedocument.documentElement.lang/japanjaja/academy/japan/tracingjaja/docsenClient-side navigation both directions, driven in a real browser:
No console errors on
/academy/japan/tracing; the page renders correctly.Images — measured against the running dev server:
Worst case — no WebP support, largest candidate — is 752 KB, under the 1 MB threshold. All four carousel images confirmed loading through
/_next/imagein the browser (complete: true), and/find-usconfirmed servingfind-us.jpgthrough the optimizer.Both re-encoded images were rendered and compared against the originals at display size; no visible quality loss. No
md-override/file covers/find-us,/docs/evaluation/overview,/japan, or/academy/japan/*.Intentionally out of scope
Other repos. Companion PR langfuse/langfuse-js#937 fixes the
js.reference.langfuse.combroken links ([MIT](LICENSE)resolving to a file that exists only at the repo root — also 404 on GitHub and npm) and adds a canonical URL to the TypeDoc site. The five/modules/packages/*404s turned out to be already fixed onlangfuse-js@main; the deployed reference site is just built from an older commit.Companion PR langfuse/langfuse-python#1858 fixes the
python.reference.langfuse.comerrors: pdoc'sindex.htmlis a bare meta-refresh stub with no title, links or canonical; the host returns that stub with HTTP 200 for every unmatched path (which is how two nonexistent…/concepts/models.mdpaths entered the crawl); and/langfusewas 2.7 MB, over the crawl limit. That PR needs the Cloudflare Pages build command repointed at its new build script to take effect —docs/is gitignored and no workflow in that repo builds it.cloud.langfuse.com/auth/*is a separate repo and separate hosting.The 9 broken
/cdn-cgi/l/email-protectionlinks are Cloudflare's Email Address Obfuscation rewriting pnpm store paths in TypeDoc's "Defined in" lines (typescript@5.9.2reads as an email address to it). Fix is a Cloudflare dashboard setting, not code.Deferred, in this repo: the remaining 22 "Image file size too large" URLs are all legacy
.gifassets in old blog and changelog posts, about half onstatic.langfuse.com. AGENTS.md says the site uses.mp4, never.gif, so the fix is re-encoding and re-uploading — a separate change, and several of the posts may simply want the asset removed.No change needed: the 4 orphan pages (
/cn,/kr,/wrapped,/oss-friends) are deliberately unlinked campaign and locale landing pages.🤖 Generated with Claude Code