Skip to content

CNanninga/bc-makeswift

Repository files navigation

Demo

https://makeswift-examples-bigcommerce.vercel.app

Visually build with BigCommerce components

In this example, you will learn how to integrate BigCommerce with Makeswift to create a visually editable ecommerce store.

This example includes a home page for listing products by category and a product template page for showing product details.

Tools


Using this example

To quickly try this example either deploy to Vercel or use our CLI.

If you have already created a BigCommerce store and know you want to use this example, scroll down to "Using your own BigCommerce store."

Deploy this example to Vercel

The deploy link below includes integrations with BigCommerce and Makeswift.

Deploy with Vercel

Note During the Makeswift integration we recommend using the the "Ecommerce - BigCommerce" template. It comes prefilled with ecommerce components.

With your deployment completed, take a tour of your ecommerce store

Use this example locally with the Makeswift CLI

  1. Run the Makeswift CLI command

    npx makeswift@latest init --template=ecommerce-bigcommerce

    Note: the --template=ecommerce-bigcommerce above will auto-select the "Ecommerce - Bigcommerce" template in Makeswift and download this example Next.js store to your local machine.

  2. Log in or sign up for Makeswift

  3. Confirm the default env vars provided

Once completed, the CLI runs yarn dev and opens Makeswift for you. From there you can use provided custom ecommerce components.

Take a tour of your ecommerce store

After integration, you will be redirected to app.makeswift.com.

  • Navigate to the "Home" page on the left to test out the custom "Header" and "Product list" components

    • The "Header" is a functional cart integrated with the BigCommerce API
    • The "Product list" is a list of products from BigCommerce. To customize the category or number of visible products, select the "Product list" and update the panels to the right labeled 'Category' and 'Count' respectively.
  • Then, go to the "__product__" page and test out the product-specific components

    • This page is also called the product template page because it is the template structure for all product pages.
    • The "Add to cart" is a functional button integrated with the BigCommerce API
    • All the other components — Product price, Product name, Product images, Product description, and Product breadcrumbs — are composable for creating a custom product page.

Using your own BigCommerce store

Once you have given the example a try it's time to use your own BigCommerce store. Here is a guide on how to set one up.

Note: the env for this example corresponds to the Vercel Commerce BigCommerce example.

How to get the environment variables from your store:

  • BIGCOMMERCE_ACCESS_TOKEN requires an API account

    • This token needs modify rights on Cart, Checkout, and storefront API Tokens, and read rights on Products and Content.
    • The "Access Token" created is the value that is used as BIGCOMMERCE_ACCESS_TOKEN
  • BIGCOMMERCE_CHANNEL_ID

    • The channel ID can be found by going to "Channel Manager" and clicking "Edit settings" on the channel you want to use. It's the number in the URL after channel/. BigCommerce Channel ID
    • Channel ID of 1 is autogenerated for all stores.
  • BIGCOMMERCE_STORE_HASH

    • The identifier for your store. It can be found in the URL of your BigCommerce dashboard BigCommerce Store Hash
  • BIGCOMMERCE_CUSTOMER_IMPERSONATION_TOKEN

    • This is a JWT. It gives your app access to the storefront API. Use this endpoint to create it. More details can be found here

    The example store token was created like so:

    curl -H "X-Auth-Token: ipupahkny78rhnuodygnrpvtl8tv0qz" -H "Content-Type: application/json" -X POST -d '{"channel_id":1,"expires_at":1982692202}' https://api.bigcommerce.com/stores/5yjdhtv55p/v3/storefront/api-token

How to add localization information to your store:

BigCommerce doesn't support localization as a first-class feature. This example uses the metafields api to store translations for each locale. Metafields are only accessible via API. This section will show you how to use the management API to add product translations.

Managing metafields with the Management API requires an API account with product "modify" permissions. This API account should be different than the one used to deploy your site.

CleanShot 2022-12-06 at 16 28 49@2x

the permission required to modify `metafields`

Once you have created the new API account you can use it with the curl commands below.

Note Don't forget to replace the PRODUCT_MODIFY_BIGCOMMERCE_ACCESS_TOKEN with the "Access Token" from creating your API account above. This token must have product "modify" permissions.

Creating locale metafields for a product

To create a metafield you will need a permission_set, a namespace, a key, and a value.

  • permission_set
    • This determines what APIs have access to this metafield. Since we query product data from the storefront API, we will need the read_and_sf_access permission_set.
  • namespace
    • This indicates the locale that this metafield belongs to. In our situation, it should match the identifier this translation belongs to.
    • A translation to Spanish would go under the es namespace.
  • key
    • The property in our product that this translation corresponds to.
  • value
    • The translated text itself.

Here is an example of how we translated the values in our plant store. Blue Lily is Lirio Azul in Spanish. To add the metafield for this translation I used the namespace of "es", the key of "name", and the value of "Lirio Azul".

curl -X POST https://api.bigcommerce.com/stores/5yjdhtv55p/v3/catalog/products/114/metafields \
   -H 'Content-Type: application/json' \
   -H 'X-Auth-Token: PRODUCT_MODIFY_BIGCOMMERCE_ACCESS_TOKEN'\
   -d '{"permission_set":"read_and_sf_access","namespace":"es","key":"name","value":"Lirio Azul"}'

Deleting locale metafields

If you make a mistake when adding a metafield, this curl command can be used to delete the mistaken metafield. Note the different HTTP method and metafield id at the end of the URL.

curl -X DELETE https://api.bigcommerce.com/stores/5yjdhtv55p/v3/catalog/products/114/metafields/24 \
   -H 'X-Auth-Token: PRODUCT_MODIFY_BIGCOMMERCE_ACCESS_TOKEN'

Updating the deployed host on Vercel

If you clicked the "Deploy" button earlier you can change the environment variable in vercel.com

Updating the locally running host

If you started out with the CLI you can update the generated .env.local with any new values from your BigCommerce store.

The example store .env.local looks like:

MAKESWIFT_SITE_API_KEY=XXX-XXX-XXX

BIGCOMMERCE_ACCESS_TOKEN=ipupahkny78rhnuodygnrpvtl8tv0qz
BIGCOMMERCE_STORE_HASH="5yjdhtv55p"
BIGCOMMERCE_CUSTOMER_IMPERSONATION_TOKEN="eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJjaWQiOjEsImNvcnMiOltdLCJlYXQiOjE5ODI2OTIyMDIsImlhdCI6MTcwNTQzMTAwNSwiaXNzIjoiQkMiLCJzaWQiOjEwMDMwMzgxMzQsInN1YiI6ImVqYnR2d3c3ZzhlejB4MXVuMXhzN2tpaGNnaTRjaTUiLCJzdWJfdHlwZSI6MiwidG9rZW5fdHlwZSI6MX0.uGUbU9ccUlKin4zKYEMkBfqXhRwXbrY6qB8wxCj95Ct0YjUfhcQYO-ppnjc_PW4i00nX4hfu0onQqO2vXTfHTQ"
BIGCOMMERCE_CHANNEL_ID=1536289

If you are struggling to configure these env vars feel free to reach out in our Discord and we will be happy to help!


Putting it all together

It's probably a good time to explain what's going on. Here is a point of reference for the technical terms below:

  • "dynamic product route"
    • This is the Next.js page that creates product pages based on BigCommerce products and our Makeswift template layout
    • It can be found here: /pages/product/[slug].tsx
    • Here is more info on dynamic routes
  • "optional catch all route"

How is BigCommerce product data getting to components?

The "optional catch all route" uses Next.js' getStaticProps to get a page snapshot from Makeswift.

const makeswift = new Makeswift(config.makeswift.siteApiKey)
const path = '/' + (ctx.params?.path ?? []).join('/')
const snapshot = await makeswift.getPageSnapshot(path, {
  siteVersion: Makeswift.getSiteVersion(ctx.previewData),
})

It also uses getStaticProps to get product data from BigCommerce.

const products = await getProducts()

Both Makeswift and BigCommerce data is then passed into the Page component via props.

return { props: { snapshot, products } }

And we wrap the MakeswiftPage with a context provider for our BigCommerce data

export default function Page({ products, snapshot }: Props) {
  return (
    <ProductsContext.Provider value={products}>
      <MakeswiftPage snapshot={snapshot} />
    </ProductsContext.Provider>
  )
}

How are product pages being generated from the template (/__product__) route?

The "dynamic product route" uses Next.js' getStaticPaths API to generate page slugs from BigCommerce products.

export async function getStaticPaths(): Promise<GetStaticPathsResult> {
  const products = await getProducts()

  return {
    paths: products.map(product => ({ params: { slug: product.entityId.toString() } })),
    fallback: 'blocking',
  }
}

The resulting pages use the same makeswift data from the template (/__product__) makeswift page.

const makeswift = new Makeswift(config.makeswift.siteApiKey)
const snapshot = await makeswift.getPageSnapshot(config.makeswift.productTemplatePathname, {
  siteVersion: Makeswift.getSiteVersion(ctx.previewData),
})

While dynamically pulling different products from BigCommerce based on the slug.

const slug = ctx.params?.slug

/* ... */

const product = await getProduct(Number.parseInt(slug.toString(), 10))

Why is the "dynamic product route" using a low revalidation period when the "optional catch all route" is using on-demand revalidation?

Pages are created in the "optional catch all route" based on pages in a Makeswift site. Since Makeswift is aware of what pages are published it can use on-demand revalidation with an api route in /pages/api/makeswift/[...makeswift].ts to rebuild pages on publish

Unlike the "optional catch all route", the "dynamic product route" creates pages based on BigCommerce products. These routes are unknown to Makeswift and thus it doesn't revalidate them on-demand. Instead, we use a low revalidation period to update them.

Why are cart API requests routed through /page/api/[checkout|cart]?

At the time of making this example the BigCommerce Storefront API is readonly and doesn't include cart mutations. In order to keep the BIGCOMMERCE_ACCESS_TOKEN private we are proxying all BigCommerce Management requests through /page/api/[checkout|cart]

More details on managing carts on a custom storefront can be found here.


Next steps

With Makeswift, you can give your marketing team hand-crafted, ecommerce building blocks to create a custom store.

To learn more about Makeswift, take a look at the following resources:

You can check out the Makeswift GitHub repository - your feedback and contributions are welcome!