Impossible to add Builder IO to Hydrogen 4

Hello there !

I followed this documentation : doc, to trying to add Builder IO (latest version) to Hydrogen V4.

→ The issue :

  • The first step i did for my project, is to setting a hydrogen project following this tutorial : Getting started with Hydrogen and Oxygen

  • Second step : I tried to add Builder IO to the hydrogen project as following the Builder IO doc I mentionned before.

  • Thirdly, I start the project with : ``` npm run dev ````

  • When i go to Builder IO, going to the ‘homepage’ page that I created, I have the below errors :


I looked at the code, searching on the whole Internet for my issue, still found nothing that can help me resolve this.

→ To know :

Can someone help please ?

Thank you in advance,

Regards,

Alexandre D

As I forget, here the packages and depedencies versions used for the project :

Hello @Alexandre_D,

Welcome to the Builder.io forum post.

Could you please check the browser console for any errors and share a screenshot with us?

Your cooperation is greatly appreciated.

Best regards,

Hello Manish-Sharma

Thank you to take in consideration my issue.
I found a solution for it.

Delete all Hydrogen routes and add the splat route ‘$.tsx’ in my project for allowing route redirection.

Thank you

Hi Aleandre_D,

did you setup hydrogen with npm create @shopify/hydrogen@latest and used the mock.shop for setup? im trying to setup builder.io too but have been running into some issues.

Hello @Jch4nni,

Welcome to the builder.io forum post.

Yes, we have also tested Hydrogen 4 with the latest version by running the command @shopify/hydrogen@latest and using the mock.shop. For detailed instructions, I’ve recorded a Loom video that you can refer to at the following link:

HI manisch-sharma,

first off thank you so much for the video. I have a few questions regarding the setup:

What node version are you using?
Which options are you choosing for hydrogen setup?

Did you create $.tsx in routes or did you use the ($Locale).$.tsx?

also i am getting this error in my console while trying to preview the testpage in builder.io:

GET 404 render /home?builder.space=be37c110ca864456808e37e9fa1872da&builder.cachebust=true&builder.preview=page&builder.noCache=true&builder.allowTextEdit=true&builder_editing=true&builder.overrides.page=0e34b2f7676b407cbf594dd9985912a9&builder.overrides.0e34b2f7676b407cbf594dd9985912a9=0e34b2f7676b407cbf594dd9985912a9&builder.frameEditing=page

fyi: i am using Ubuntu 22 lts and node 20

and i also noticed that after i created $.tsx and pasted your code i am getting this console error:

✘ [ERROR] Node builtin “vm” (imported by “node_modules/@builder.io/sdk-react/lib/edge/blocks-fe027bf7.js”) must be polyfilled for the browser. You can enable this polyfill in your Remix config, e.g. browserNodeBuiltinsPolyfill: { modules: { vm: true } } [plugin browser-node-builtins-polyfill-plugin]

Hello @Jch4nni,

To resolve the polyfilled error, you can add the below code in your remix.config.ts

  browserNodeBuiltinsPolyfill: {
    modules: {
      vm: true,
    },
  },

Additionally, I used the $.tsx file located in the routes directory to integrate builder.

Hi manish-sharma,

i managed to install and connect builder io.

i still get cant connect to localhost in the preview so i cant build the page. BUT i can publish it and access the empty page on my localhost - so the connection works at least.

are there any ports i might need to enable for builder in the firewall or anything?

this is a screenshot of the network for builder.io:

and the output from my dev console:

fyi: i am working on a ubuntu vm behind a server firewall

Update: I used an ngrok tunnel to project my localhost to an url - which works, i can now access the hydrogen site everywhere. But the preview is still failing.

builder3

Any ideas?

Hello @Jch4nni,

You can try enabling the Proxy Previews option from Settings → Advanced Settings → Advanced and see if that helps fix the preview

hi @manish-sharma ,

i managed by overriding the headers set by hydrogen. I also tried your solution with advanced settings but it didnt work. One issue remains tho:

I can publish a site “test-page” and access & edit it in the preview once published - so the url would be localhost:3000/test-page, but if i wanna edit the “landing page” meaning localhost:3000/ i can see the preview, but i still get a connect error and can’t edit the page.
There are no new errors in console or network, so am i missing smt?

Hello @Jch4nni,

I noticed that hydrogen typically uses the _index.tsx file for the landing page. Have you tried integrating the Builder code into the _index.tsx file? This could potentially resolve the issue you’re experiencing with the landing page.

Hello @Jch4nni,

I updated the routes → _index.tsx code to something like below and it worked for me

import {defer, type LoaderFunctionArgs} from '@shopify/remix-oxygen';
import {Await, useLoaderData, Link, type MetaFunction} from '@remix-run/react';
import {Suspense} from 'react';
import {Image, Money} from '@shopify/hydrogen';
import type {
  FeaturedCollectionFragment,
  RecommendedProductsQuery,
} from 'storefrontapi.generated';
import {
  fetchOneEntry,
  isEditing,
  isPreviewing,
  Content,
} from '@builder.io/sdk-react/edge';

export const meta: MetaFunction = () => {
  return [{title: 'Hydrogen | Home'}];
};

export async function loader({context}: LoaderFunctionArgs) {
  const {storefront} = context;
  const {collections} = await storefront.query(FEATURED_COLLECTION_QUERY);
  const featuredCollection = collections.nodes[0];
  const recommendedProducts = storefront.query(RECOMMENDED_PRODUCTS_QUERY);

  const page = await fetchOneEntry({
    model: 'page',
    apiKey: 'Your API Key',
    userAttributes: {
      urlPath: `/`,
    },
  });

  return defer({featuredCollection, recommendedProducts, page});
}

export default function Homepage() {
  const data = useLoaderData<typeof loader>();
  const {page} = useLoaderData<typeof loader>();
  return (
    <div className="home">
      <FeaturedCollection collection={data.featuredCollection} />
      <RecommendedProducts products={data.recommendedProducts} />
      <Content
        model="page"
        apiKey="Your API Key"
        content={page}
      />
    </div>
  );
}

function FeaturedCollection({
  collection,
}: {
  collection: FeaturedCollectionFragment;
}) {
  if (!collection) return null;
  const image = collection?.image;
  return (
    <Link
      className="featured-collection"
      to={`/collections/${collection.handle}`}
    >
      {image && (
        <div className="featured-collection-image">
          <Image data={image} sizes="100vw" />
        </div>
      )}
      <h1>{collection.title}</h1>
    </Link>
  );
}

function RecommendedProducts({
  products,
}: {
  products: Promise<RecommendedProductsQuery>;
}) {
  return (
    <div className="recommended-products">
      <h2>Recommended Products</h2>
      <Suspense fallback={<div>Loading...</div>}>
        <Await resolve={products}>
          {({products}) => (
            <div className="recommended-products-grid">
              {products.nodes.map((product) => (
                <Link
                  key={product.id}
                  className="recommended-product"
                  to={`/products/${product.handle}`}
                >
                  <Image
                    data={product.images.nodes[0]}
                    aspectRatio="1/1"
                    sizes="(min-width: 45em) 20vw, 50vw"
                  />
                  <h4>{product.title}</h4>
                  <small>
                    <Money data={product.priceRange.minVariantPrice} />
                  </small>
                </Link>
              ))}
            </div>
          )}
        </Await>
      </Suspense>
      <br />
    </div>
  );
}

const FEATURED_COLLECTION_QUERY = `#graphql
  fragment FeaturedCollection on Collection {
    id
    title
    image {
      id
      url
      altText
      width
      height
    }
    handle
  }
  query FeaturedCollection($country: CountryCode, $language: LanguageCode)
    @inContext(country: $country, language: $language) {
    collections(first: 1, sortKey: UPDATED_AT, reverse: true) {
      nodes {
        ...FeaturedCollection
      }
    }
  }
` as const;

const RECOMMENDED_PRODUCTS_QUERY = `#graphql
  fragment RecommendedProduct on Product {
    id
    title
    handle
    priceRange {
      minVariantPrice {
        amount
        currencyCode
      }
    }
    images(first: 1) {
      nodes {
        id
        url
        altText
        width
        height
      }
    }
  }
  query RecommendedProducts ($country: CountryCode, $language: LanguageCode)
    @inContext(country: $country, language: $language) {
    products(first: 4, sortKey: UPDATED_AT, reverse: true) {
      nodes {
        ...RecommendedProduct
      }
    }
  }
` as const;