Problem
The recent latest-version redirect work correctly handles documentation routes, but product-specific landing routes bypass the shared /_library/$libraryId/$version parent.
Live examples currently returning 200 with self-referencing canonicals:
- /query/v5 and /query/latest
- /router/v1 and /router/latest
- /ai/v0 and /ai/latest
This leaves duplicate landing pages even though nested latest-version docs correctly return 308.
The product-specific routes call beforeLoadLibraryLanding in src/routes/-library-landing-route.tsx. That helper validates a version but does not redirect library.latestVersion to latest. The current latest-version check in src/routes/_library/$libraryId/$version.tsx does not govern these static landing routes.
Google canonical guidance: https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls
Desired behavior
- /{library}/{library.latestVersion} permanently redirects with 308 to /{library}/latest.
- Preserve the remainder of the request URL where applicable, including meaningful search parameters.
- Every indexable library landing page, including historical numbered landing pages that remain accessible, declares /{library}/latest as its canonical landing URL.
- og:url and twitter:url match the /latest canonical.
- No numbered library landing page self-canonicalizes.
- Existing historical documentation behavior remains unchanged: historical docs may remain accessible and use their current path-aware canonical logic.
Acceptance criteria
- The shared product landing helper enforces the latest-numbered-version redirect for every product-specific landing route.
- Tests cover at least Query, Router, AI, and one library with non-v1 latestVersion metadata.
- /query/v5, /router/v1, and /ai/v0 return 308 to their /latest equivalents in an integration test.
- Historical landing pages that return 200 emit only one canonical link, pointing to /latest.
- /latest landing pages self-canonicalize and remain 200.
- Sitemap entries continue to contain only /latest library landing pages.
- Stable unversioned aliases such as /query are reviewed and use a permanent redirect when their mapping to /latest is intentional.
Problem
The recent latest-version redirect work correctly handles documentation routes, but product-specific landing routes bypass the shared /_library/$libraryId/$version parent.
Live examples currently returning 200 with self-referencing canonicals:
This leaves duplicate landing pages even though nested latest-version docs correctly return 308.
The product-specific routes call beforeLoadLibraryLanding in src/routes/-library-landing-route.tsx. That helper validates a version but does not redirect library.latestVersion to latest. The current latest-version check in src/routes/_library/$libraryId/$version.tsx does not govern these static landing routes.
Google canonical guidance: https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls
Desired behavior
Acceptance criteria