Repository navigation
Indexable Hungarian and Spanish pages with hreflang (SEO spec 3) - #236
Conversation
/hu and /es used to 302 to /?lang=, which served the English HTML with canonical /. No Hungarian or Spanish page could be indexed. Now the landing page and the five free tool pages are prerendered in Hungarian and Spanish at their own addresses (/hu, /es, /hu/tools/vita-idozito, /es/tools/cronometro-debate, ...). Each has <html lang>, a self-canonical, and hreflang for en, hu, es and x-default. The sitemap carries the same alternates as xhtml:link, and check-site fails the build on hreflang that is one-sided or disagrees with <html lang>. src/config/localized-routes.json is the one list of addresses. Opening a translated address chooses its language like a ?lang= link, so Start leads into the app in that language. Picking another language there moves to that language's address. The client keeps the canonical on the translated address after it takes over. Trial length and Pro price on these pages now come from site.json through i18next default variables, in all three languages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed.
|
| Layer / File(s) | Summary |
|---|---|
Localized route registration and language selection src/config/localized-routes.json, src/lib/seo/localized-routes.ts, src/lib/url-language.ts, src/main.tsx, src/lib/route-modules.ts, src/App.tsx, src/components/LocalizedRoute.tsx, vercel.json, src/test/vercel-deployment-config.test.ts, e2e/localization.spec.ts, .claude/skills/verify-debatelab/..., docs/operations.md |
Hungarian and Spanish paths map to page loaders and set the route language. Legacy homepage ?lang=hu and ?lang=es URLs redirect to localized paths. Tests and documentation describe the localized routes and language switching. |
Localized tool pages and navigation src/pages/tools/localized/*, src/components/free-tools/ToolPageLayout.tsx, src/components/landing/*, src/i18n.ts, src/locales/*, src/locales/tools/*, docs/operations.md, .claude/skills/verify-debatelab/recipes/localization.spec.ts |
Hungarian and Spanish copy supplies the tools index and four tool pages. Shared components render localized content and links. Pricing strings use configured trial and Pro price values, and landing-page links use localized paths. |
Prerendering and localized SEO output src/prerender/entry.tsx, src/lib/seo/*, scripts/prerender.mjs, scripts/sitemap.mjs, scripts/generate_seo_content.py, scripts/check-site.mjs, public/llms.txt, src/test/seo/page-head.test.tsx, docs/operations.md |
Prerendered pages include language and alternate-link metadata. Canonical URLs and structured data use localized routes. Sitemap and llms.txt output includes localized entries, and check-site validates hreflang targets and alternate sets. |
Estimated code review effort: 4 (Complex) | ~60 minutes
Sequence Diagram(s)
sequenceDiagram
participant Browser
participant App
participant localizedRouteLoaders
participant LocalizedToolPage
participant LocalizedRoute
participant ToolPageLayout
Browser->>App: Request a localized tool URL
App->>localizedRouteLoaders: Load the route page module
localizedRouteLoaders->>LocalizedToolPage: Resolve the configured tool route
App->>LocalizedRoute: Render with route and language
LocalizedRoute->>LocalizedToolPage: Provide route language
LocalizedToolPage->>ToolPageLayout: Render localized copy and tool links
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Note
🎁 Summarized by CodeRabbit Free
-
Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Essentials by visiting https://app.coderabbit.ai/settings/billing.
Comment @coderabbitai help to get the list of available commands.
/?lang=hu and /?lang=es render the English page with canonical /, so Google can list them as alternates of /. A 301 for the homepage only sends them to /hu and /es. Vercel appends the original query to a redirect destination, so the browser lands on /hu?lang=hu. That URL is canonical to /hu, and the client drops ?lang= on load. ?lang= on every other path, such as /app?lang=hu, keeps the client's own handling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The slugs now match what the pages call each tool: vitaidomero, vitatetel-generator and jegyzetlap, in place of vita-idozito, vitatema-generator and flow-lap. None was ever live, so no redirects. Links, sitemap, hreflang and llms.txt follow from localized-routes.json. The 19 copy fixes from the #236 review correct grammar, calques and ambiguous words. The /hu title now says "vitafelkészülés". The tools hub and motion generator heads say "vitatétel" like the page bodies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts resolved:
- i18n.ts: keep both default variable sets, product/brand/host from
main and trialDays/proMonthly from this branch.
- en/es/hu.json: main's new hero headline and subheadline, this
branch's {{trialDays}} trial badge.
- prerender/entry.tsx, check-site.mjs, docs/operations.md: keep both
sides (main's entity graph and FAQ checks, this branch's localized
pages and hreflang check).
GuideHub on /hu and /es now shows only the free tools at their
localized addresses, plus one link to the English guides on the home
page ("Angol nyelvű útmutatók", "Guías en inglés"). The Hungarian tool
labels use this branch's names (Vitaidőmérő, Vitatétel-generátor,
Jegyzetlap), and "cáfolást" follows the review.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This is Spec 3 of the SEO sprint (
seo-sprint/cody-specs.md). It makes Hungarian and Spanish pages indexable and adds hreflang.What changes
/huand/esare real pages now.vercel.jsonno longer has the 302 from/:lang(es|hu)to/?lang=. The build prerenders the landing page and the five free tool pages in Hungarian and Spanish. Each one gets<html lang>, its own title, description, H1 and canonical, and its own JSON-LD (WebPage/WebApplicationwithinLanguage, plus a localizedFAQPagethat matches the visible FAQ)./hu/tools,/hu/tools/vitaidomero,/hu/tools/vitatetel-generator,/hu/tools/jegyzetlap,/hu/tools/beszedido-kalkulator. These were renamed after review (see below); none was ever live, so they need no redirects./es/tools,/es/tools/cronometro-debate,/es/tools/generador-mociones,/es/tools/hoja-de-flujo,/es/tools/calculadora-tiempo-discursosrc/config/localized-routes.jsonis the one list. The router, route loaders, prerender,check-siteand the llms.txt generator all read it. Documented indocs/operations.md.en,hu,esandx-default(English) in the head.sitemap.xmlrepeats them asxhtml:link, read from each page's own head so there is only one source. Pages without equivalents get none.check-sitenow fails on hreflang that doesn't resolve, leaves out the page itself orx-default, disagrees with<html lang>, or isn't the same set on every page it names./huchooses Hungarian the same way?lang=hudoes, so Start leads into the app in Hungarian./humoves to that language's address,/esor/./huinstead of flipping back to/. A unit test covers this; it fails without the fix.site.json. The trial length and Pro price on the landing and tool pages were hard-coded "3" and "$5" in all three catalogs. They now read{{trialDays}}and{{proMonthly}}, which i18next fills fromsite.json.termsPage.p4(legal text) is unchanged.?lang=homepage links. A homepage-only 301 invercel.jsonsends/?lang=huand/?lang=esto/huand/es, so those URLs stop showing up as alternates of/. Vercel appends the original query to redirect destinations (production shows/hu?x=1going to/?x=1&lang=hu), and plainredirectshave no option to drop it. The real target is therefore/hu?lang=hu. That is harmless:/huis canonical to itself, and the client removes?lang=from the address on load.?lang=en, unknown values and every other path (/app?lang=hu,/login?lang=hu) are not redirected. A case invercel-deployment-config.test.tscovers this.generate_seo_content.pychange is one function plus one template line, kept away frominternal_links().Footer.tsxandShortAnswer.tsxchange only their/toolslink to the localized address (3 lines each). Hero and Navbar are untouched.Content limits on the translated tool pages
formats.ts, but they won't update if that file changes.For Spec 1 (
seo/internal-links-brand-entity)Spec 1's guard test isn't on main yet, so this PR doesn't add one. To make it language-aware:
/hu/...page should need ≥3 inbound links from/hu/...pages, with the English home also counting./huand/esget links from every translated tool page's header and breadcrumb./huand/estoo. It needs a decision there: keep the links to English guides, or hide the hub on translated pages./only.Merged main (
92d7113a: #233, #235, #234)git merge origin/mainat6d20371d. There was no rebase and no force-push.i18n.tskeeps both default variable sets:product/brand/hostfrom main andtrialDays/proMonthlyfrom this branch./huand/esshows only the free tools, at their localized addresses, plus one link to the English guides ("Angol nyelvű útmutatók", "Guías en inglés"). No English guide list appears there.?lang301 still answers/?lang=huwith301 /hu?lang=huon the local Vercel-like server.npm run verifyat6d20371dpassed (exit 0): 655 unit, 30 collaboration, 482 edge, build with check-site and check-links clean, 47 smoke e2e. The sitemap now has 52 URLs (40 English + 12 translated), 18 of them with hreflang. Every/huand/espage has 5 inbound links.Review follow-up (
seo-sprint/pr-review-233-236.md)Slugs renamed before anything is indexed:
vita-idozitobecamevitaidomero,vitatema-generatorbecamevitatetel-generator, andflow-lapbecamejegyzetlap. Links, sitemap, hreflang and llms.txt follow fromlocalized-routes.json.All 19 Hungarian fixes from the review are applied:
/hutitle: "vitafelkészülés"/hu/toolstitle: "vitatételek"Following the review's "pick one term" for fix 19, the tools-hub description and the motion-generator title and description in
hu.jsonpageHeadalso say "vitatétel" now. The rest of the app's Hungarian UI still says "indítvány"; changing that is a separate decision.Still open for Adam: POI as "közbekérdezés" or "közbeszólás", "felkészülési keret" or "felkészülési időkeret", and "eset" for case. These are terminology choices from the review, not errors.
Acceptance evidence
Curl against the built
dist/, served locally the way Vercel serves it withtrailingSlash: false(/xservesx/index.html).vite previewcan't do this, because it falls back to the landing page for every path without a trailing slash,/toolsincluded. Only a deployment can prove the redirect is gone from Vercel, and I made no preview deployment.sitemap.xmlhas 57 URLs (45 before), 18 of them with hreflang. The new/huand/esentries carry the English landing page's lastmod (2026-10-23), because the build dates the landing page by its last source commit andsrc/locales/isn't in that list. That date is earlier than the pages but harmless.The
?lang=redirect, on the same local server, which appliesvercel.jsonredirects withhasconditions and appends the original query the way production does.vercel devdoesn't supporthaslocally, so only a deployment proves the real behaviour.In a browser,
/?lang=hufollowed the 301 to/hu?lang=hu, and the client then showed/huwithlang=huand canonical/hu./?lang=es&utm_source=xended on/es?utm_source=x. The switcher on/hu→ English went to/, and a reload stayed there with no loop./app?lang=huwas not redirected and opened sign-in in Hungarian.In a real browser on the same server, after the app took over:
/hukeptlang=huand canonical/hu;/eskeptlang=esand canonical/es. No page errors./huwent to/loginwithlang=huand the title "Bejelentkezés a DebateLabba"./humoved to/es.ef88cddc); the review fixes don't change the/huand/eslanding pages except the/hutitle.|
|
|
|
|
|
|
|
|
/huphone ||
/hudesktop ||
/esphone ||
/esdesktop |Start from
/hulanding on sign-in in Hungarian:Verification
GitHub Actions is billing-blocked, so these are local results, not CI.
npm run verifypassed atef88cddc, again after the?langredirect (b1aa06a5), and again at the current headfe00edc5. The browser checks below ran atef88cddc.npm run verifypassed (exit 0): docs check, lint, typecheck, 651 unit tests (652 fromb1aa06a5), 30 collaboration tests, 482 edge tests, build (prerender, sitemap, check-site, bundle boundaries), service-worker test, and 47@smokee2e tests on desktop Chromium.e2e/localization.spec.tsande2e/free-tools.spec.tson desktop and mobile Chromium: 36 passed.public-pages,hungarian-parity,startup-shellandhome-navigationon desktop and mobile Chromium: 56 passed.verify:fullsuite. Three failures already known on main live there:loading-performance.spec.ts:63,navigation-performance.spec.ts:344andsearch-quality.spec.ts:7.verify-debatelabreciperecipes/localization(updated here) driven against local Auth, Postgres and Edge Functions (fake model mode): 5/5 on desktop-chromium and 5/5 on mobile-chromium, including the newloc-linkscheck that Start from/hureaches the app in Hungarian.Terms to review
Hungarian (Adam):
Spanish:
🤖 Generated with Claude Code
Summary by CodeRabbit