Home

Awesome

Pack Hydrogen Demo - A simple example storefront powered by Pack + Hydrogen

<img width="1000" alt="image" src="https://cdn.shopify.com/s/files/1/0807/6515/7649/files/Screenshot_2023-09-07_at_12.56.39_PM_1024x.png?v=1694116680">

Demo | Pack Platform

About

About Pack:

Build and manage your Custom Storefront with Pack, a Hydrogen-based Digital Experience Platform

Welcome to Pack, your ultimate solution for creating exceptional storefronts that captivate your audience and drive results. Discover how Pack redefines the way you approach content management, design, and performance to unleash the full potential of your brand.

Meet the Hydrogen-Pack Starter:

Introducing Hydrogen-Pack Starter, a customized Hydrogen starter that showcases how Pack can power your custom Shopify storefronts. With Pack, you can seamlessly connect to Shopify, leverage prebuilt React components + third party integrations, and design engaging shopping experiences.

Features

Explore the capabilities that make Pack stand out:

Our Approach

At Pack, we believe in simplicity and empowerment:

What's included

Getting started

Requirements

Environment Variables

Before you can run your application locally, you will need to create an .env file at the root of your project with your shop's domain and Storefront API token. You can copy the necessary values from the Pack Storfront by going to Settings -> Developer, then Copy All under the Storefront Variables section. See the example below:

SESSION_SECRET="XXX"
PUBLIC_STOREFRONT_API_TOKEN="XXX"
PUBLIC_STORE_DOMAIN="XXX"
PACK_PUBLIC_TOKEN="XXX"
PACK_SECRET_TOKEN="XXX"

Building for production

This command will simulate the same deployment job that Shopify Oxygen will use when deploying your live site.

npm run build

Building for local development

This command will start a server locally on your machine at http://localhost:3000.

npm run dev

Pack Customizer Content

You can access the data in the Pack Customizer by using the pack object that lives in the Hydrogen context. See the following example:

export async function loader({params, context, request}: LoaderArgs) {
  const {handle} = params;
  const storeDomain = context.storefront.getShopifyDomain();

  const searchParams = new URL(request.url).searchParams;
  const selectedOptions: any = [];

  // set selected options from the query string
  searchParams.forEach((value, name) => {
    selectedOptions.push({name, value});
  });

  const {data} = await context.pack.query(PRODUCT_PAGE_QUERY, {
    variables: {handle},
  });

  const {product} = await context.storefront.query(PRODUCT_QUERY, {
    variables: {
      handle,
      selectedOptions,
    },
  });

  ...
}

The data object will contain all the Pack Section Setting content provided by CMS Authors in the Customizer. This data will be define per each Section's Setting schema. While the product object will contain any Shopify speficic data provided by the Storefront API.

See https://docs.packdigital.com/for-developers/section-api/schema.

Caching

Pack is leveraging the same Caching Strategy available with the Hydrogen framework. For an example of this, check out the @pack/client

export function createPackClient(options: CreatePackClientOptions): Pack {
  const {apiUrl, cache, waitUntil, preview, contentEnvironment} = options;
  const previewEnabled = !!preview?.session.get('enabled');
  const previewEnvironment = preview?.session.get('environment');

  return {
    preview,
    isPreviewModeEnabled: () => previewEnabled,
    async query<T = any>(
      query: string,
      {variables, cache: strategy = CacheLong()}: QueryOptions = {},
    ) {
      const queryHash = await hashQuery(query, variables);
      const withCache = createWithCache<QueryResponse<T>>({
        cache,
        waitUntil,
      });

      // The preview environment takes precedence over the content environment
      // provided when creating the client
      const environment =
        previewEnvironment || contentEnvironment || PRODUCTION_ENVIRONMENT;
      const fetchOptions = {
        apiUrl,
        query,
        variables,
        token: options.token,
        previewEnabled,
        contentEnvironment: environment,
      };

      // Preview mode always bypasses the cache
      if (previewEnabled) return packFetch<T>(fetchOptions);

      return withCache(queryHash, strategy, () => packFetch<T>(fetchOptions));
    },
  };
}

Data Layer

The Pack StarterKit will submit pageView and addToCart (coming soon) to Shopify Analytics via the Hydrogen hook. See the following article for more details: https://shopify.dev/docs/api/hydrogen/2023-07/utilities/sendshopifyanalytics

For example on how events are submitted view the products route (app/routes/products.$handle.tsx):

export async function loader({params, context, request}: LoaderArgs) {
  ...

   if (!data.productPage) {
    throw new Response(null, {status: 404});
  }
  // optionally set a default variant, so you always have an "orderable" product selected
  const selectedVariant =
    product.selectedVariant ?? product?.variants?.nodes[0];

  const productAnalytics: ShopifyAnalyticsProduct = {
    productGid: product.id,
    variantGid: selectedVariant.id,
    name: product.title,
    variantName: selectedVariant.title,
    brand: product.vendor,
    price: selectedVariant.price.amount,
  };
  const analytics = {
    pageType: AnalyticsPageType.product,
    resourceId: product.id,
    products: [productAnalytics],
    totalValue: parseFloat(selectedVariant.price.amount),
  };

  return defer({
    product,
    productPage: data.productPage,
    selectedVariant,
    storeDomain,
    analytics,
  });
}