Parent
#553 — Spec: one session for Elastic Path identity
What to build
A search engine or link preview fetching a category page receives the products in the HTML
instead of an empty shell — which is what has forced the package to recommend a weaker listing
component for pages that matter for ranking.
A consumer mounts nothing and sets no property to get this.
Spec stories 17, 18, 27.
Acceptance criteria
Blocked by
The tracker's dependency graph on this issue is authoritative; this list mirrors it.
Below is the original ticket, kept intact — it carries the research and decisions from #486, #495, #523 and #524.
In brief
Catalog search currently renders only in the browser. A search engine or a link preview fetching a category page gets an empty shell, which is why the package has historically pointed people at a different, weaker listing component for pages that matter for SEO.
This issue renders the first page of results on the server so the products are in the HTML.
One honest limitation, accepted deliberately: the server pass renders the default, unfiltered first page. Category pages work correctly because their scope comes from a component property rather than the URL. A deep-linked search URL such as ?query=boots renders the unfiltered page and then corrects itself once the page loads in the browser — acceptable, because search result pages are conventionally excluded from search engines anyway.
Part of the ADR-0003 token architecture. Decided on #524, facts from #523.
Why
The listing-path recommendation (catalog search for everything, SSR and SEO-critical pages included) is conditioned on this landing.
Work
Unconditional <InstantSearchNext> swap — no prop, no separate component. No call site names a transport, a designer has no basis to reason about SSR, and a registered prop is permanent once shipped.
Require-only, never mixed with import for the InstantSearch packages. require of both works; import of one plus require of the other yields two react-instantsearch-core copies, two contexts, Invariant failed, and an SSR 500 on every request. The package's require-everywhere style becomes a load-bearing invariant rather than a style.
baseFilter dev warning, firing on server pass + enableUrlSync + empty baseFilter. SSR is correct only because category scope rides <Configure filters>; a designer can equally scope a category page with EPHierarchicalMenu/EPRefinementList off the URL — identical in Studio, fine in the browser, wrong only in the HTML. The heuristic cannot tell a category page from a search page, so the copy must say "if this is a category page", not assert a defect. Making baseFilter required was rejected: a search page legitimately has none, and a newly-required prop is a break.
Server-render failure falls through to client rendering and must never 500 the page. A deliberate narrowing of the keep-the-error-slot rule to the client side: a shopper always sees the hydrated render, whereas the alternative is a crawler indexing "Catalog Search is not available" for a category page, and a transient proxy blip becoming a cached SEO failure.
What SSR delivers, and does not
It server-renders the unrefined default first page. <Configure query/filters/hitsPerPage> flows; initialUiState and routing-derived URL state do not, and useSearchParams() is empty during the server pass even under force-dynamic — so skipping conditionally is foreclosed, not rejected. A deep-linked ?query=boots or refinement URL renders unrefined and self-corrects on hydration. Accepted: those pages are conventionally noindex and were never the SEO case.
Consumer wiring is zero — no route, no prop, nothing to mount.
Acceptance criteria (original — folded into the list above)
Blocked by: the platform enablement issue, the dependency floors issue, and the catalog-search shim issue.
ADR-0003: plasmicpkgs/commerce-providers/elastic-path/docs/adr/0003-one-session-for-elastic-path-identity.md. Map: #486. Issue set: #496.
Parent
#553 — Spec: one session for Elastic Path identity
What to build
A search engine or link preview fetching a category page receives the products in the HTML
instead of an empty shell — which is what has forced the package to recommend a weaker listing
component for pages that matter for ranking.
A consumer mounts nothing and sets no property to get this.
Spec stories 17, 18, 27.
Acceptance criteria
Blocked by
The tracker's dependency graph on this issue is authoritative; this list mirrors it.
Below is the original ticket, kept intact — it carries the research and decisions from #486, #495, #523 and #524.
In brief
Catalog search currently renders only in the browser. A search engine or a link preview fetching a category page gets an empty shell, which is why the package has historically pointed people at a different, weaker listing component for pages that matter for SEO.
This issue renders the first page of results on the server so the products are in the HTML.
One honest limitation, accepted deliberately: the server pass renders the default, unfiltered first page. Category pages work correctly because their scope comes from a component property rather than the URL. A deep-linked search URL such as
?query=bootsrenders the unfiltered page and then corrects itself once the page loads in the browser — acceptable, because search result pages are conventionally excluded from search engines anyway.Part of the ADR-0003 token architecture. Decided on #524, facts from #523.
Why
The listing-path recommendation (catalog search for everything, SSR and SEO-critical pages included) is conditioned on this landing.
Work
Unconditional
<InstantSearchNext>swap — no prop, no separate component. No call site names a transport, a designer has no basis to reason about SSR, and a registered prop is permanent once shipped.Require-only, never mixed with
importfor the InstantSearch packages.requireof both works;importof one plusrequireof the other yields tworeact-instantsearch-corecopies, two contexts,Invariant failed, and an SSR 500 on every request. The package's require-everywhere style becomes a load-bearing invariant rather than a style.baseFilterdev warning, firing on server pass +enableUrlSync+ emptybaseFilter. SSR is correct only because category scope rides<Configure filters>; a designer can equally scope a category page withEPHierarchicalMenu/EPRefinementListoff the URL — identical in Studio, fine in the browser, wrong only in the HTML. The heuristic cannot tell a category page from a search page, so the copy must say "if this is a category page", not assert a defect. MakingbaseFilterrequired was rejected: a search page legitimately has none, and a newly-required prop is a break.Server-render failure falls through to client rendering and must never 500 the page. A deliberate narrowing of the keep-the-error-slot rule to the client side: a shopper always sees the hydrated render, whereas the alternative is a crawler indexing "Catalog Search is not available" for a category page, and a transient proxy blip becoming a cached SEO failure.
What SSR delivers, and does not
It server-renders the unrefined default first page.
<Configure query/filters/hitsPerPage>flows;initialUiStateand routing-derived URL state do not, anduseSearchParams()is empty during the server pass even underforce-dynamic— so skipping conditionally is foreclosed, not rejected. A deep-linked?query=bootsor refinement URL renders unrefined and self-corrects on hydration. Accepted: those pages are conventionallynoindexand were never the SEO case.Consumer wiring is zero — no route, no prop, nothing to mount.
Acceptance criteria (original — folded into the list above)
next/*specifiers match 0.3.21's.Blocked by: the platform enablement issue, the dependency floors issue, and the catalog-search shim issue.
ADR-0003:
plasmicpkgs/commerce-providers/elastic-path/docs/adr/0003-one-session-for-elastic-path-identity.md. Map: #486. Issue set: #496.