How to Build a Storefront with Nuxt.js and BigCommerce
Storyblok is the first headless CMS that works for developers & marketers alike.
In this tutorial, we will use Storyblok to build a storefront with BigCommerce and Nuxt.js. You can find the source for this tutorial on Github, the take a look at the demo: storyblok-storefront-nuxt.vercel.app
If you are in a hurry, you can download the whole source code of the project at Github github.com/storyblok/big-commerce-nuxt-starter or jump into one of the following chapters.
Storyblok Space
Sign up for a free Storyblok account & choose Create a new space {1}. Then name your Storefront {2}, and click the create space {3} button.
Once you create a new space, follow our eCommerce Storefront documentation for setting up your storefront in Storyblok. After you finish this, you should have some basic components set up like in the image below {1}.
eCommerce Integration
Before you can move to Nuxt.js and build your Storefront, you must set up your Integration plugins. Follow the BigCommerce guide on how to retrieve your endpoint credentials and then the integration plugin guide on how to set it up. Once your integration field-type plugin is working, you should be able to select some products or categories on your Storyblok components like in the image below {1}.
Storefront in Nuxt.js
We have prepared a Nuxt.js starter template to show you how to connect the eCommerce plugin with the eCommerce API to build your storefront. For this example, you will use the BigCommerce API as your eCommerce provider. You can take a look at the Demo before getting started.
Start by cloning the starter repository.
Connecting your Storyblok Space with the Starter
To connect to the storefront space created in the storefront tutorial, get your tokens from the Storyblok Space Settings {1} under API-Keys {2}.
Fill the Location (default environment)
{4} as well as the Preview URLs
{3} field with your localhost URL http://localhost:3000/
. Don't forget the trailing slash /
. If you have a staging or production server, the default environment can also be set to a different staging URL {4}.
Copy the preview token {2} into the nuxt.config.js
file. Exchange accessToken
with the preview token of your space.
You will also need your eCommerce endpoint and tokens. Open the nuxt.config.js
file and add the storeUrl
and storeToken
into the env
object at the beginning of the file.
If you don't want to add them directly, you can also make use of the .env-template
and rename it to .env
. Then enter the following variables:
These .env
variables are then loaded via the process.env
variable in the nuxt.config.js
file:
nuxt.config.js
If the API is CORS restricted, you might need to create a separate token for your localhost/production server. In the case of BigCommerce & Nuxt.js, you need to create a new token for http://localhost:3000 for the local development and then create a different token with the real URL once you deploy your store.
After you add your tokens, you can start the development server:
Changing the Real Path Field
When you open your Home Page in Storyblok, you will see a page not found
error. Since Storyblok automatically creates a /home
path from the Home story, you want to redirect that to your base URL in the Nuxt application /
.
To fix this routing issue, change the real path of your homepage. When you open the home entry, you should already see the running localhost on port 3000 {1}. Now navigate to the config tab {2} and change the real path field to /
{3}.
Reload the page and you should see your Nuxt.js application in the preview space. Be sure you hit the Save button before reloading.
If all goes well, you should see a similar preview to the one below, which is already loading the right components. If you named your components differently in Storyblok, some of the components won't be loaded. We will get to that in the next section. Make sure you have your Dev Preview set up to see the localhost on port 3000 {3}. Components should be editable, so when you click on them, they should open in the editor on the right {2}.
Understanding the Components
A few components are already defined in the Starter, but take a look at what is happening with the components in more detail. Since Storyblok is built to prioritize a component-based approach, you will find the same components in Storyblok and the Nuxt starter template. Once Nuxt loads your Story from the Storyblok API it will automatically inject the right components based on their order in the CMS.
Index.vue
Check out the Index Page. In the <template>
part, you iterate over all the components created in the storefront tutorial: the teaser, the category bar, the featured product. Storyblok then injects the correct Nuxt component based on the name of the component in Storyblok. If the Storyblok Component can't be mapped to a component in the Nuxt Starter, it will inject a Placeholder component.
In the asyncData()
function, which is specific to Nuxt.js, you load your Home story from the Storyblok API. By making use of this function, you're fetching and rendering the data on the server-side.
In the mounted()
function of your index.vue
, we're loading the Storybridge to enable live editing in our editor.
index.vue
All the components are loaded globally in the plugins/components.js
file.
plugins/components.js
Notice that the different Components, like the Hero component, are injected with a matching string blok-hero
. Let's take a look at a specific component to understand the connection to Storyblok:
Product Grid
In the documentation for setting up a Storefront in Storyblok, a component called Product Grid was created. Now we want to display some categories {1} to the left and some products to the right {2}, like in the image below.
When you click the arrow icon on the top right {1} and then Draft JSON {2}, you should see the associated data from your home story that is returned from the plugin.
If you set up your components and plugin field-types correctly you should see the following data:
The API always returns a story object {1} with a content object {2}. In the Home entry there is a body with a collection of bloks {3} which returns an array of components. If you look at the second component in this array, you can see that it's the Featured Products
component with the eCommerce integration plugin set up {6}. The plugin has a property items {7} with an array of products. Each product has an id {8} to query the product from the eCommerce API. It also returns whether this item is a product or a category {9}.
If we take a look at the first component Hero
, we see it has a component property with the technical name of the component {4}. This name will be used later to match the right component in your Nuxt application in plugins/components.js
.
It also has an _editable
property {5} which is used to enable the live editor and passed to our components. This property is only available in the draft version of a story.
Now let's take a look at the component implementation in the components/ProductGrid.vue
file.
components/ProductGrid.vue
What the component essentially does is loop through the items returned by the eCommerce field-type and load the categories and products on the client-side. This is not ideal for performance, but makes sure all your prices and products are up to date without the need to rebuild the entire site. In the mounted
function we also sort the products to the order of the products and categories in Storyblok, so you can reorder them from within Storblok in any way you want. If you wanted to load the data on the server side, you would need to do that beforehand in the asyncData
function of the index.vue
file. Since the plugin only saves the id, you query the complete categories and products from the eCommerce API. So the path ends up like category/kitchen
. The pages the categories and products link to are auto-generated in pages/categories/_path.vue
and pages/product/slug.vue
. Looking at this template for the category page, you can see that it gets the correct category from the BigCommerce API and loads it with all its products with the asyncData
function.
pages/categories/_path.vue
In the end, you will have an auto-generated page for each category that looks similar to the image below. You can also check out the page in the demo.
Custom Product Detail Page
You might want to create custom pages for specific products that have some additional content as seen in the Demo, where a quote is added to a product.
To get there, set up a folder called product
to allow for custom Product Detail Pages and create one entry with a specific slug, as described in the storefront setup tutorial. When you open this entry now and the product with this slug exists also in your eCommerce API, you should see a product preview page. The visible content is loaded via the slug parameter in the URL {1}. Now you can add some additional content in Storyblok like a headline {2} and a description {3}. If additional content is available in Storyblok, it will replace the headline and description loaded from the eCommerce API {2, 3}. All the other content like the price {4} will still be loaded from the eCommerce API.
If you take a look at your template file for products in pages/product/_slug.vue
, you can see that there are two requests. One is to the BigCommerce API to get the details for the product, like the Price and Product Description, and another one is to Storyblok to get the details for this product, if they exist in Storyblok. Otherwise, it will only load the product from the eCommerce API.
pages/product/_slug.vue
Finally, you can show the additional Storyblok information in the template if your request finds a product in Storyblok. With v-editable you can make the editable part in Storyblok clickable for the editor.
Now there is some custom content on the Product Detail Page.
By connecting two headless systems you can allow a very flexible structure and reorder any content with Storyblok's powerful visual editor.
Deployment
You can deploy your Storefront by running the Nuxt generate command, which creates a deployable directory dist
:
We can deploy Nuxt applications on any service like Vercel or Netlify. Read more about the deployments on the Nuxt documentation. If we want to deploy for example with Vercel, we would need an Vercel account and their CLI tool. Then we can deploy the dist
directory with the Vercel CLI:
Conclusion
Connecting two headless based systems like BigCommerce and Storyblok can greatly enhance your workflow and the user experience. With Storyblok's Visual Editor you get a great editing experience, while still keeping all your store and product information in your eCommerce system. The other big advantage is in terms of performance. With a JAMstack based storefront, you can decrease page loading times and hopefully increase purchases. If you want to learn more about why Storyblok is a great choice as a CMS for your eCommerce experiences, we recommend reading our article CMS for eCommerce.