A Centra catalog plus Sanity editorial chrome plus Next.js Instant Navigations sounds like a clean split until URLs disagree. Centra knows the nested category tree and the leaf segment per locale. Sanity knows curated collection pages you wrote on purpose. Both can emit paths. Only one should own automated PLP and PDP segments.
I treat CanonicalPath as Centra-owned: the lowercased leaf of the nested category URI for that locale. Sanity keeps editorial slugs for hand-built collections. When the request path does not match CanonicalPath, the app 308s to the Centra leaf. Query strings are not a free-for-all. ?page=N when N is greater than 1 is the only query allowed on canonicals, hreflang alternates, and redirect targets. Everything else drops. SEO stays boring on purpose.
Hreflang and sitemap URLs come from Centra translations per locale. I do not clone one English href across languages and hope Google figures it out. Each locale gets its own leaf from Centra's tree. Sanity URLs stay in the editorial lane.
The Instant Nav bug was sneakier than the redirect rules. The PLP route always awaited searchParams. That made sense for pagination: you need ?page= before you render the grid. It also meant the static shell could not paint on a soft navigation when the path already matched CanonicalPath. Collection pages looked stuck on loading after Instant Nav even though the segment was correct. The shell waited for search params that were empty.
The fix splits on path match. When the incoming path already equals CanonicalPath, skip awaiting searchParams for the shell. Paint the collection frame immediately. On mismatch, still await so ?page= survives the 308. Redirect logic and Instant Nav shell logic share the same ownership rules but different await boundaries.
const pathMatchesCanonical = requestPath === canonicalPathForLocale;
const shell = pathMatchesCanonical ? (
<CollectionShell locale={locale} category={category} />
) : (
<CollectionShellWithSearchParams locale={locale} category={category} />
);Pagination inside the shell can still read ?page= where it matters. The outer route stops blocking the whole tree on an empty query object during soft nav.
Wrong slug, 308 to Centra's leaf, allowlisted query only. Matching slug, shell without the searchParams await. Editorial Sanity paths stay editorial. Automated commerce paths stay Centra-shaped. Instant Nav stops feeling like a loading screensaver.
Happy coding! Sander