Adding Store Locator to Catalyst

As we dive into the world of Catalyst, we’re taking a fresh look at each of our apps to see how we adapt them to be more composable.

The first app that we’ve looked at is Store Locator. It’s the perfect candidate as it’s already a react app that fetches locations from our API. The difference is the delivery mechanism. In the Stencil environment, it’s a PageBuilder widget which can be dropped on the page and this adds the necessary markup and JS to render the store locator.

What we’ve done, is abstract out the frontend component into its own package so that it can now be installed into any React project.

Let’s run through how to add Store Locator to Catalyst.

The first step is to install our package:

npm install @hypa-apps/store-locator

While you’re there, we also recommend installing some Mapbox dependencies as we’ll use them later for some stylesheets:

npm install mapbox-gl
npm install @mapbox/mapbox-gl-geocoder

Next, let’s add a helper to fetch store locations from the API. Create the file client/queries/get-hypa-store-locations.ts and add the following:

import { StoreLocatorResult } from '@hypa-apps/store-locator';

export const getHypaStoreLocations = async (
  storeHash: string,
  channelId: string,
  groupId?: string,
): Promise<StoreLocatorResult> => {
  const path = `https://storelocator.hypaapps.com/store-locator/${storeHash}/${channelId}${groupId ? `/${groupId}` : ''}`;

  try {
    const response = await fetch(path);
    // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
    const data = (await response.json()) as { data: StoreLocatorResult };

    return data.data;
  } catch (error) {
    return {
      locations: [],
      allTags: [],
      active: false,
    };
  }
};

Ok, now we need a new page to add our store locator to. Let’s create app/[locale]/(default)/our-stores/page.tsx.

We can then add our store locator component to our new page.

import { StoreLocator } from '@hypa-apps/store-locator';

import '@hypa-apps/store-locator/dist/css/store-locator.css';
import 'mapbox-gl/dist/mapbox-gl.css';
import '@mapbox/mapbox-gl-geocoder/dist/mapbox-gl-geocoder.css';
import { getHypaStoreLocations } from '~/client/queries/get-hypa-store-locations';


export default async function OurStores() {
  const { locations, allTags, active } = await getHypaStoreLocations(
    process.env.BIGCOMMERCE_STORE_HASH ?? '',
    process.env.BIGCOMMERCE_CHANNEL_ID ?? '1',
  );

  return (
    <div className="mx-auto max-w-screen-xl">
      <h1 className="my-6 my-8 text-4xl font-black lg:my-8 lg:text-5xl">Our stores</h1>

      <div className="my-10">
        <StoreLocator
          active={active}
          allTags={allTags}
          locations={locations}
          mapboxApiKey={process.env.MAPBOX_API_KEY}
        />
      </div>
    </div>
  );
}

You’ll notice that we’ve used the BigCommerce store hash and channel environment variables and provided that to our API helper function.

We also need to add a new MAPBOX_API_KEY environment variable to our .env.local file.

Now, you can open http://localhost:3000/our-stores in your dev environment and see your new store locator!

One nice thing about this change is that locations are fetched server-side rather than client-side in the current stencil environment. Vercel’s data cache will then cache this response.

In the future, we can see adding support for turning this into a Makeswift component with just a few more lines too.

Tom Robertshaw
Stay up to date with Hypa news and features