diff --git a/packages/samples/headless-ssr-commerce/app/products/[productId]/page.tsx b/packages/samples/headless-ssr-commerce/app/products/[productId]/page.tsx
index e968419c120..2208ae33475 100644
--- a/packages/samples/headless-ssr-commerce/app/products/[productId]/page.tsx
+++ b/packages/samples/headless-ssr-commerce/app/products/[productId]/page.tsx
@@ -1,6 +1,8 @@
import * as externalCartAPI from '@/actions/external-cart-api';
import ContextDropdown from '@/components/context-dropdown';
import ProductPage from '@/components/pages/product-page';
+import StandaloneProvider from '@/components/providers/standalone-provider';
+import StandaloneSearchBox from '@/components/standalone-search-box';
import {searchEngineDefinition} from '@/lib/commerce-engine';
import {NextJsNavigatorContext} from '@/lib/navigatorContextProvider';
import {defaultContext} from '@/utils/context';
@@ -34,9 +36,13 @@ export default async function ProductDescriptionPage({
},
});
return (
- <>
+
Product description page
+
Loading...
}>
- >
+
);
}
diff --git a/packages/samples/headless-ssr-commerce/components/providers/standalone-provider.tsx b/packages/samples/headless-ssr-commerce/components/providers/standalone-provider.tsx
new file mode 100644
index 00000000000..a32a78d16ed
--- /dev/null
+++ b/packages/samples/headless-ssr-commerce/components/providers/standalone-provider.tsx
@@ -0,0 +1,72 @@
+'use client';
+
+import {
+ StandaloneHydratedState,
+ StandaloneStaticState,
+ standaloneEngineDefinition,
+} from '@/lib/commerce-engine';
+import {NavigatorContext} from '@coveo/headless-react/ssr-commerce';
+import {PropsWithChildren, useEffect, useState} from 'react';
+
+interface StandalonePageProps {
+ staticState: StandaloneStaticState;
+ navigatorContext: NavigatorContext;
+}
+
+export default function StandaloneProvider({
+ staticState,
+ navigatorContext,
+ children,
+}: PropsWithChildren) {
+ const [hydratedState, setHydratedState] = useState<
+ StandaloneHydratedState | undefined
+ >(undefined);
+
+ // Setting the navigator context provider also in client-side before hydrating the application
+ standaloneEngineDefinition.setNavigatorContextProvider(
+ () => navigatorContext
+ );
+
+ useEffect(() => {
+ standaloneEngineDefinition
+ .hydrateStaticState({
+ searchAction: staticState.searchAction,
+ controllers: {
+ cart: {
+ initialState: {items: staticState.controllers.cart.state.items},
+ },
+ context: staticState.controllers.context.state,
+ },
+ })
+ .then(({engine, controllers}) => {
+ setHydratedState({engine, controllers});
+
+ // Refreshing recommendations in the browser after hydrating the state in the client-side
+ // Recommendation refresh in the server is not supported yet.
+ // controllers.popularBoughtRecs.refresh();
+ });
+ }, [staticState]);
+
+ if (hydratedState) {
+ return (
+
+ {/* // TODO: KIT-3701: Type 'React.ReactNode' is not assignable to type 'import(".../node_modules/@types/react/index").ReactNode'.
+ Type 'bigint' is not assignable to type 'ReactNode'.*/}
+ <>{children}>
+
+ );
+ } else {
+ return (
+
+ {/* // TODO: KIT-3701: Type 'React.ReactNode' is not assignable to type 'import(".../node_modules/@types/react/index").ReactNode'.
+ Type 'bigint' is not assignable to type 'ReactNode'.*/}
+ <>{children}>
+
+ );
+ }
+}