DEV Community

CarsonJ
CarsonJ

Posted on

4 hours lost to a trailing slash: what shipping multilingual SEO actually looks like

The setup

I have a tool site with 6 languages. Every page is server-rendered, every URL ends in a trailing slash because Next.js generates it that way. Should be straightforward. Should be done in an afternoon.

It took 4 hours and a lot of staring at rendered HTML.

What broke

The first sign something was off: my Chinese pages were not showing up as their own URLs in Google Search Console. They were getting merged with the English version of the same page. The English one ranked. The Chinese one disappeared.

I opened a Chinese tool page. Looked at the source. Found the canonical URL. It pointed to the Chinese page. That part was correct.

Looked again. It pointed to the Chinese page with a trailing slash. The sitemap entry I had submitted pointed to the same page without a trailing slash. Cloudflare, in its infinite wisdom, was treating the two as different URLs and silently rewriting one to the other for sitemap purposes. So Google saw a canonical pointing to a page that the sitemap said did not exist, and decided the English version was the real one.

The whole thing was two characters long.

The actual fix

Three things had to line up:

  1. Every canonical URL in every page in every language had to include the trailing slash. Including the hreflang cross-language hints.
  2. The sitemap had to match. Same trailing slash, same case, same query string handling.
  3. Cloudflare's URL rewrite rules had to stop being helpful. The default behavior was fine for users; it was lethal for crawlers.

Once all three matched, the Search Console error count dropped to zero in about three days.

What I learned

  • Canonical URLs and trailing slashes are not the same thing. A page and its canonical are two separate things the crawler compares. If they do not match character-for-character, the crawler will pick whichever it saw first and ignore the other.
  • Cloudflare is rewriting your sitemap in ways you cannot see. Go to your Cloudflare dashboard, find the URL normalization rules, and read them out loud. Then do the same for any plugin that touches href attributes.
  • hreflang pointing to itself is technically valid and a total SEO footgun. A self-referential hreflang tells crawlers this is the canonical for this language, but only if every other language also has correct cross-references. Miss one and your international SEO is just gone.
  • Trailing slash, lowercase, no query string. Pick one canonical form for your entire site and use it everywhere. The cost of inconsistency is invisible until it is not.

Why I still think browser-based tools are worth the SEO pain

I run a small collection of free browser-based tools at korelyy.com — emoji mixers, life-in-weeks calculators, regex testers, the kind of stuff that does not need a backend. The SEO work is genuinely annoying. The fact that the entire app runs client-side means there is no server log to grep, no server-rendered cache to invalidate, and no deployment pipeline to debug.

It is a tradeoff. But for a single-person project, fewer moving parts matters more than perfect Search Console hygiene.

What's next

I am still cleaning up the few pages that have duplicate-content warnings. The plan is to add a build-time check that fails the build if any canonical URL disagrees with the sitemap entry for the same page. If that works I will open source the script.

If you have shipped multilingual SEO at any non-trivial scale, what was the one bug that ate the most hours?

Top comments (0)