Skip to content

SEO remediation: canonical host redirect, noindex thin compare pages, sitemap lastmod#15

Merged
gavdevs merged 6 commits into
mainfrom
fix/seo-deindexing-remediation
Jul 5, 2026
Merged

SEO remediation: canonical host redirect, noindex thin compare pages, sitemap lastmod#15
gavdevs merged 6 commits into
mainfrom
fix/seo-deindexing-remediation

Conversation

@gavdevs

@gavdevs gavdevs commented Jul 4, 2026

Copy link
Copy Markdown
Member

Why

Google deindexed the site almost entirely: ~9,000 pages indexed mid-April → 5 pages by mid-May (GSC coverage export). Two root causes:

  1. Host duplicationwww.unclouded.app and plain http:// served 200 instead of redirecting. Google indexed www duplicates (visible in live search results); canonical <link> tags are only a hint.
  2. Scaled thin content — 25,684 auto-generated /compare/ pages (83% of all sitemap URLs) with no unique content. GSC shows 9,658 pages "Crawled - currently not indexed" with failed validation — the signature of a site-wide quality suppression.

Changes

  • 301 redirect www/http → https://unclouded.app in the worker (scoped to prod hostnames; dev and workers.dev untouched)
  • X-Robots-Tag: noindex on /compare/ pages; comparisons sitemap now returns 410 and is removed from the sitemap index (pages remain usable in-app)
  • 301 trailing-slash normalization (was 307)
  • Remove Crawl-delay: 10 from robots.txt (ignored by Google, throttled Bing)
  • <lastmod> in app + alternatives sitemaps (KV cache keys bumped to v2)
  • KV cache: 7-day default TTL so stale data self-heals without manual purge; stop writing null results (they re-read as misses anyway)
  • Fix hydration mismatch: grid layout localStorage read moved to post-mount effect

Verification

  • pnpm build (vite build + tsc) passes, biome clean on changed files
  • Prod behavior verified pre-change via curl: www/http 200s, 307 trailing slash, no lastmod

🤖 Generated with Claude Code

gavdevs added 4 commits July 4, 2026 17:53
- 301 www.unclouded.app and plain-http to https://unclouded.app (Google
  was indexing www duplicates; canonical tags alone are only a hint)
- 301 trailing-slash normalization instead of the router's 307
- X-Robots-Tag: noindex on /compare/ pages and 410 the comparisons
  sitemap: 25k thin auto-generated pages triggered site-wide quality
  suppression (GSC: 9.6k 'Crawled - currently not indexed', 5 pages
  left indexed by mid-May)
- remove Crawl-delay from robots.txt (ignored by Google, throttles Bing)
- add <lastmod> to app and alternatives sitemaps
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 4, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
unclouded e8b07a4 Commit Preview URL

Branch Preview URL
Jul 05 2026, 12:09 AM

gavdevs added 2 commits July 4, 2026 18:02
Some seeded rows have updated_at values that produce an Invalid Date;
toISOString() threw RangeError and 500'd the app/alternatives sitemaps.
The seed import wrote ISO strings into the integer updated_at column,
so drizzle's timestamp mapper produced Invalid Date for every row and
sitemaps rendered without lastmod. Select the raw value for sitemaps,
normalize ISO strings and epoch seconds/millis, and make the import
write epoch seconds to match the schema going forward.
@gavdevs gavdevs merged commit c735d03 into main Jul 5, 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.

1 participant