Building High-Performance Online Stores with Shopify Hydrogen and Remix

Rate this content

I. Introduction

- Overview of Shopify Hydrogen and Remix

- Importance of headless e-commerce and its impact on the industry

II. Setting up Shopify Hydrogen

- Installing and setting up Hydrogen with Remix

- Setting up the project structure and components

III. Creating Collections and Products

- Creating collections and products using Hydrogen’s React components

- Implementing a Shopping Cart

- Building a shopping cart using Hydrogen’s built-in components

VI. Building the home page with Storyblok

- Cloning the space and explaining how it works

- Implementing Storyblok in the repo

- Creating the Blok components

- Creating the Shopify components

- Implementing personalisation

104 min
17 Oct, 2023


Sign in or register to post your comment.

AI Generated Video Summary

The Workshop covered various topics including building a homepage with Hydrogen and Storyblok, querying data using storefront.query and storefront.mutate, building collection indexes and details, adding items to the cart and displaying cart data, connecting Storyblok and adding a development server, setting up environments and creating page routes, using Storyblok and creating page components, personalizing the homepage based on user behavior, integrating Storyblok with Shopify components, and closing remarks.

1. Introduction to Hydrogen and Building the Homepage

Short description:

We are here today to introduce the __ loop behind React. Today, we are working with Spana and Omikasa to hear from them. Hydrogen is built on top of Remix with some packages and an integration of packages. The website we're going to build is the homepage, which is built with hydrogen and Storyblok. It includes a banner, a grid of products, and a single product. Personalization is introduced to display different information based on the customer's behavior. The workshop includes instructions on cloning the repo, creating the.env file, and running npm install.

We are here today to introduce the __ loop behind React. Today, we are working with Spana and Omikasa to hear from them. Before that, please join us in welcoming Omikasa. I wanted to give a talk about hydrogen because I think it's very interesting that Shopify create its own framework and when I begin with it, where we sell our components and then they bought Remix. And so I learned Remix because of hydrogen.

In the beginning, what is funny is I was not attracted to Remix because I'm more frontend and the food stag, etc. And I come from freelancing. Now, I am a dev rel at Storyblok. And what happens, I really fell in love with Remix because it makes everything easier because it's based on the web standards. And so my new talk in conferences is about web standards in Remix. So, it was a double win because I learned hydrogen and I found my favorite framework this way. So, basically, hydrogen is really built on top of Remix with some packages and an integration of packages. Sorry, I have to stop my notifications. The Shopify APIs.

So, let's begin. I'm going to share my screen. To begin, we have this Notion page where I have all the information, all I'm going to say, and all the code is there. So, this is the URL. So, please go there to follow up. It's a short URL, slash hydrogen. Okay? And after that, you will clone this repository so you have the link on the Notion page. And while you're doing that, I'm going to show you the final website that we are going to build.

So this is the website that we're going to build. So this is your homepage. And the homepage is built with hydrogen but also with Storyblok, which is a headless CMS with a visual editor that has extension to integrate commerce in it. So here, first we have a banner, and here we have a grid of products. So these products are pulled from Shopify, but we can see them visually, you know, in the visual editor here. And then we have a single product. And this single product pulls this from Shopify, and this from the CMS, and everything is visual. So I'm going to show you also how this is built.

Now, if we go to find your board here, we are led to the entries for the Shopify connection. So we have a performance board and original board. So if we go to performance boards, here, we see all the collection details with all the Shopify products. So this is 100% Shopify and not Storyblok. And now I can go to my product details. Here I have a Buy Now button and Add to Cart button. So I add the cart, and you can see here's a number of items in my cart. And then if I go to the cart, I can check out. So it's a and I can also remove products. It's a functional, simple e-commerce. I took a free theme from Shopify and to copy the style and take inspiration to make this nice surf website. And now if I come back to the homepage, you can see that this banner has changed. Now it's featuring performance board. And this grid is only a performance board, too. And this is because I have introduced some personalization. I don't know if you heard about personalization, but it's really a high trend now in e-commerce. It means that depending on the behavior of the customer, we are going to display different information. So here, as I have navigated to the performance board, I assume that this user, me, is interested in performance board. So when it comes back to the website, I serve performance boards to drive sales, of course. So I will show you also how this is built in the back office with Storyblok and in the code and how all this works.

So now, I don't know if you have already cloned the repo? And also the notion page? When it's done, you create a.env file. I think there is perhaps a.env example. And here you have all the necessary tokens because I already have a Shopify instance and so you don't have to create it. And you have all the tokens so you will get all the products from there. So please raise your hand if it's not finished. So after that, you clone the repo here. So I will wait five minutes so everybody can do it. And then you run npm install. And after that you create the.env file. And you stay for the moment on the main branch and we are going to progress by branches. Okay, when you are ready, you just run npm run dev or h2dev works also, which is shortcuts. And you should have this. Okay. So I'm going to comment the repo. So to create this, I have create the comment with the comment lines by. So if we go to a hydrogen Shopify. And if we go to the docs, getting started, okay. If we run this command, I let you try this by yourself because last time I did a workshop in four hours and it was taking too much time. But if you run this command, you will have a full featured e-commerce with everything including user registration, search orders, everything you can find and with mock data. So from there you can explore or customize it.

2. Using the Hello World Template and Querying Data

Short description:

In this part, the speaker discusses using the Hello World template and building on top of it. They explain the basic structure of a remix and how to import layouts and wrap outlets. The speaker also introduces the use of storefront.query and storefront.mutate for getting and manipulating data. They mention some challenges with the Hello World template and suggest referring to the documentation. The speaker then guides the audience in creating a query to get the collection index and retrieving the necessary data in the component. They offer assistance and give instructions to try the exercise. The part concludes with a mention of the collections branch.

But in this case, I have used the Hello World template. I think it's another command, so here there is just tutorials that I recommend also if you want to work alone, I learned everything from there and the documentation is really well done. So, okay, let's show this, where is the Hello World command? I just wanted to show... Okay, I don't find a Hello World command now, but it's a basic template and I have built on top of this.

And here what I have already installed because we want to focus on Hydrogen and not on all the basic things. I have installed Tailwind. I also have created the basic things like your footer, okay. A header with just a logo and a menu with just a link to the collections named board and a layout. And so this is a remix. And in remix we have a root file which is the parent root. And so we import the layout here and we wrap our outlet. So the outlet will display the other routes. And so we wrap the layout here. And then we have the index root which is created by default. Here we have the end file. And server.js is our entry point. And this is when you use the Hello world template all this is created for you. So you have this function create store from client and you create the store front with it and it pass all these N variables here. Then it's best to get that context. And so it would be available in the global context of remixes, loaders and actions. So for the ones who don't know remixes it's a full stack framework and loader functions get data from the server and action functions create mutations on the server. So with the storefront, we will be able to make to get data with storefront.query and with storefront.query, we will get the data to create the collections, to create the products, to read the data from the cart and with storefront.mutate, we will perform GraphQL mutations to create the cart operations. Okay, and so everything is full stack, these functions happen on the server and they are the same file from the components where you load the data from the server. So all the components are full stack. So any questions about that? You're muted. I cannot hear you. Well, I'm fine. I'm already happy that I got the environment running, so. Okay. What I wanted to say also, yes, when you install the Hello World template, you don't have that. And so it was a few weeks ago I have to read this talk in Amsterdam. Yes, no, in Croatia, because I have this in Croatia. And what happens, it changed many things. And they had this new content security policy and nothing was working. So this is not the perfect way to do it. There is things in the documentation. So I make it in a quick way like that. Because of that, the image was not working. The scripts neither. So this is something I had on top of the template, just to know what is immediately available and what you have to create. OK, so if your template is working, your repo is working, let's go back to Notion. So now we are going to create the collection of N products. So this is what I was explaining, a storefront query and storefront mutate. We can do this exercise if you want. We can try. So if we go to localhost 3000 and slash GraphQL, we have access to the GraphQL schema. OK? So from there, we want to create a query to get the collection index. So in the collection index, what we have, we have the image from the collection. We have the title and we have a handle that links to the collection details. So we need all that. So we need to create this query. So we can create it in GraphQL. We can search there. Then we need to write it in the root. So I show you the root. Oops. We need to create a root for that. OK. So you can look into the documentation. I will let you have 15 minutes for that. And then we need to write a loader function to query the necessary data. So data from our collection. Then we need to retrieve this data in the component with use loader data hook, which is a hook from Remix to retrieve the data from the server. And then to write a component just to display a collection title. Perhaps it's a bit too much, if you don't know hydrogen, but do you want to try? Do you want the solution immediately? I will give it a try. OK, go! OK. So I'm going to explain because it will be easier. So for that, you go to the branch. To collections. This branch, no one, one collections.

3. Building Collection Index and Details

Short description:

In this part, the speaker provides the code for creating a root collection index and writing a collection query. They explain the use of the storefront query to retrieve collection data from the server and demonstrate the retrieval of data in a component using the loader data hook. The speaker also introduces the collection card component and the shopping hydrogen react library. They discuss the components for displaying currency, price, and a Buy Now button. The speaker mentions that the collection details will be built next, including pagination and product information.

And so you will have all the code. And so you create, all the code is here also. If you want to rebuild step-by-step and try to do things by yourself, I have written all the code in this here. And so you create a root collection index. And this is where you write your collection query. So if I test, you see, we get the ID, the title, the handle, and the image. So if I test this query, oops. Into here. You see, I get all my collection performance board and original board, okay?

So then we write our loader function, and as I was explaining before, we pass the query to context storefront dot query. As you remember, we have storefront available in our context. So this will get the collection data from the server. And here is our component, and here we retrieve this data. We use loader data hook, and so we have the data for our collections.

And I don't know who is not muted, so because I hear somebody. I know it's you Peter. I think you have noise. I'm sorry I'm in the Co-working space. Yeah, working space. I will mute myself. I work in a co-working space, but it's just next to my house so when I have workshops or things I come back home. So it's very practical. It's the next door to my house. Yes, and then I have created a component collection card, which is here. And here I also use, for example, this component and this shopping hydrogen react. It's a library that you can use with any react framework. So you can use it with Next also. Of course, I would better recommend to use hydrogen and Remix. And so, for example, here's an image component. You just need to pass the data to get the image and we will see all the components. We have one for displaying the currency and the price, which is then money. We have a Buy Now button, and there is components for the card that I will not use here because we are going to be the server-side card is more efficient, but if you want to use it with other frameworks, you can look into this library and you can make shop in an easier way. But I think it's better to work with Remix and Hydrogen. So here we have our handle. We use a link component from Remix. Here we have a title and an image and everything is tied with Tailwind. If we go back to our collection index, with that, we display our collections. Any question about that? All good? Okay. Next, we're going to build the collection details. Let's go there. Here, same thing. We have a collection query, and we have also all this data is for the pagination which is a new component in Hydrogen. First time I gave this talk because this was the talk before being the workshop. I have to do it by hand, but now they have a competent for pagination, so you need to pass all that, the first, last, third cursor and cursor. Then all the collection details that you need. ID, title, description, as an image as if we go to our collection here. We have the title, we have the image, and then we have the products. We have this pagination, we can load more. We need the products, a first number of product we want by page. So in the first load, before and after the page info, all that you have in GraphQL and the node for the products. So the ID, the title, the date of publication, the handle, the variance with the image, and for the image, we want the URL, the outtake, the width and height, the price, the amount and the currency code, and the compareAtPrice is for discounted products. Okay, then again, we have our loader, and here we get the collection details, which again start from query and we pass our query as well as the pagination variables. So we have this function, getPaginationVariables from Shopify Hydrogen, and here we put the number of products by page. And we pass in the pagination variable, and all that is to build the pagination. I will not enter in details through the mechanism of that, but it makes the pagination really easy to make. Then we get our collection data. Again, we use loader data and from there, we have all the info to build our collection. So okay, so we have here the collection image, a collection title here as out of the image. Here's the collection title and the product grid. I have created another component here and this is where I use the pagination. I also have created a product card. Here's so first, let's see the product card. So here I'm using this money component I was commenting before and I create a variable is discounted. So if the compared price amount is superior to the price, the product is on sale, is discounted. So here I have the handle to my product details. Here, okay, if it's discounted, I display a sale badge. Here I have the image. So I only put one image. We have an array of image, so I take only the first one of the variants and here, okay, the money display a price. And here's the discounted price. So this is for the product card and the product grid.

4. Building Collection and Product Display

Short description:

In this part, the speaker explains how to pass a collection as a prop and implement pagination. They also discuss creating a route for the product handle and retrieving product data dynamically. The speaker demonstrates returning specific data from the loader and the importance of filtering data on the server side. They mention the need for the store domain for the shop pay button. The part concludes with the speaker mentioning the upcoming work on building the homepage with Storyblok and the creation of the cart.

So here I pass my collection as prop. And here we have this pagination component and we just have to pass collection product into the connection and the nodes of the next link and it's loading. And then the pagination will work. So we pass here's a product card and we map around the nodes and the product and each product. And here we have the link to load more products.

Okay, so this was for the collection details. Any question about that? No, for me no. Okay, okay, good. Other people have questions? Okay somebody has right or good. Okay, so we can continue. Then now we have our collections and now we want to display. So you have all the code here. We want to display our product. So for that we go to the next branch, number two, product. So, okay, and here I have created this route, the product handle. And in this route, again this is the same principle I create my product query, okay? With all the data I want for my products. So the ideas, the handles, the vendors, the descriptions, the featured image, the option, the selected, the variant by selected option that I renamed selected variant, the image price, et cetera. I let you explore that. I just want to show you how everything works.

And again, I have my loader and I get, so here we will load the product dynamically depending on the handle. So yes, in my query, I have the handle as variable, and so I get my handle from the params. And I pass again my product query to the Storefront query. And I pass the handle and the selected options as variables. And here I get the selected options from the search params. And from there again, okay and I return, so here in Remix, in Azure and in Remix, we return from the loader what we want, so what is great in Remix also we are on the server. So we could return only the data that we want. Here I have not returned also product, but if I wanted only the title, I return only the title. So we can filter the data from the server and this avoid to have unnecessary data on the front end and it makes everything faster. We want also the store domain. This is for the shop pay button, so it's a buy now button, and we need to pass the store domain to have this shop pay button working. And okay, so let's run this. Okay, I return all that and here again, we've used the data. I retrieve all these data as a product, the selected variant at the store domain. So here it is orderable. Okay, I see if my selected variant it's available for sales. If we have a predict image too. And then we have all the data to display our product. For the moment we just have the short pay button. We have not, not done have the add to cart because we are going to build a cart together, which is one of the biggest part of this workshop. Okay, any questions? Maybe, but it's a bit Storyblok related. Storyblok comes after. Okay, okay. Yeah, yeah, yeah. For the moment, we are, we still, if you look in the front end, okay, in npm install, so, oops. No, no, I don't mind. Okay, if we go to localhost 3000, you can see our homepage is still empty, okay, but we still hope there is something about the standard is not right. Okay, but we have, okay, have a problem with a problem on this branch, it seems, well, with Tailwind, but we have all our data and we will build the homepage with Storyblok, and first we are going, we build the collections, the products, then the part, then we will have all the Shopify part working, we will work on Storyblok, okay? So, any... I'm sorry. Yeah, that's okay. I just was wondering about something else, but it's a more about the combination on the product detail page with Storyblok components, but it's maybe a bit off topic. No, no, it's not off topic. It's at the end. Okay, that's cool, that's cool. It's the last part. I will wait. Other people, do you have questions? Okay. We can make a pause of five minutes, or do we want to continue? Because now we're going to create the cart. Maybe we could continue. I don't know for the others. Yeah, please continue, yeah. Okay. Okay, so now we're going to create the cart. So cart operation could be done on the client side, but this would cause a performance degradation because of the additional code delivered to the browser, so it would also affect the customer experience as critical flows won't be actionable until all JavaScript has finished loading. But Remix is a powerful mutation API that uses web standards like Form Element and HTTP, so we can implement a traditional service-side form workflow while keeping the benefits of client-side user experience. And so thanks to that, we can do progressive enhancement, optimistic UI, all these good stuff, because this part will work without JavaScript. Not the one that we are building because I use Suspense at the moment for some reasons, but what I mean is you can, with Remix in general, you can bring applications that don't even need JavaScript to work. But actually, here JavaScript and React, it's here for enhancing user experience or interactivity, but all the functionality can work without JavaScript. So this is really a great thing. So let's build the performance server side Trard and improve our store and the customer experience. So we go to the next branch, number three, Kart.

5. Adding Items to the Cart and Displaying Cart Data

Short description:

To add items to the cart, initialize the Kart with Create Kart Handler in server.js. Import the kartForm component to create an add to cart button. Define the products to add to the cart with the line, including quantity and variant ID. Return the cart form to indicate the route where it will be processed. Place the cart button in the product details page. The remove from cart button works similarly. In the cart route, use a switch statement to run the cart add lines or cart remove lines functions based on the cart action. A cart empty component is displayed if the cart is empty. To display cart data, create a loader in the route file. This will be used globally to read data in the header and cart route.

Okay, I don't know if we need NPM. Perhaps run NPM install because I think I have all the packages like icons that are in this branch and now if we go to the front end. Okay, you see we have a Kart here. Okay, now my CSS is right too and from there when we've all that, we are able to add items to the Kart so after that all the, and to remove them too. Okay, we can remove them here and we can check out okay? So first to build that, we initialize the Kart with Create Kart Handler. So this is in server.js, so the entry file. Okay, I'm going to see if there was questions. Okay so we import Create Kart Handler and we create this fetch inside the fetch request we create the Kart Handler. By passing the storefront and functions to get the Kart ID and set the Kart ID. This will use a basic query but you can, you can look at the documentation and find more options to pass to this Kart Handler. Then we pass this Kart to getLoadContext so our Kart now will be available with some functions in our context. So, I show it in the code. So in Server.js. We have our Create Kart handler. Here we have our fetch. And we have here our Create Kart handler that we pass here in getLoadContext. Okay, so this is a first step. Now, our Kart is available. So, now, we have this function, but we need, of course, to add items to our kart and to be able to remove them. So, we are going to create add to kart button. So for that, we import the kartForm component and this kartForm component abstracts away a lot of complexity. So, this is when I gave this talk for the first time in May at the RemixConf and it was not existing. And I gave it several times and I was giving it in Croatia and one week before I realized that hydrogen evolves a lot and I had the panic attack for one week because I had to change all my slides and everything. So, it's so great because hydrogen is really evolving fast and being abstractured that makes the user, the developer experience easier. But for me it was really a panic because I had to change all that and there was this code bank security policies. But okay that's a little story. It makes really things easier. So, we define what to add to the cart with the line. So, ta-da-da. Okay, here in the lines we define what we want to have to the cart, the quantity and the merchandise ID which is the variant ID. And then we just need to return this cart form to indicate the route where it will be processed. The action, here is lines has. It will trigger a function we're going to see that after. And the inputs, we pass the lines. So the inputs, the lines are the products that we are going to add to the cart. And we have our button which is nested in the cart form. So this ensures that the click translates to add items to the cart. Thanks to the actions, lines has. And all this action is directed to our cart route. So then we place our cart button into our product details page. So product dollar handle under the short pay button, okay? So if we go here, we have the... So also what they have done here, I have put all my cart components in the folder, but this is my way to do things. You can do it how you want. So I have here my Add to cart button, okay? And okay, so cart form, the lines, and everything is there. And then in my product handle, I have now my Add to cart button and I pass the variant ID, which is a selected variant ID, okay? Then the Remove from cart button work the same. So remove from cart, to cart, okay, remove from cart button here. So here we have again our cart form, but here is action, it's lines remove and the inputs are the line IDs it's a product to remove, and our button here it's an icon. Okay, then I think I have an action, normally to, yes, then in the cart route, so I have a cart route here. I have this action, and so I have a switch, and depending on the cart action, so if it's line hard, I will run the cart add lines function. And if it's, the action it's line remove, I will run the cart remove lines functions. Okay, so this is how it works. Any questions about that, about the add to cart and remove from cart button? Nope, nope. Okay, everybody's okay? Okay. Okay, so okay, we installed the react icons, but that's already done. Okay, remove from cart button, okay, that's I have explained that. The cart root is here. Okay, we also built a cart empty component that will appear if our cart is empty. So this is very simple. Okay, we have your cart is empty and a link to the collection page to continue shopping. So now we have a cart. We have a button to add items into it. So now we need to grab the cart and read data to display it. So we're going to need this data into places. We have this icon in the headers that displays a number of items. So we need to read it from the header. And of course we need to also read these data in the cart route. So as we need the data into place, we need it globally. So we are going to create a loader in the route file because the route file is the parent route. So here in our loader, we create... So we have something special here because...

6. Handling SEO and Creating Cart Components

Short description:

In the root file, an SEO component is used to handle SEO. The shop name is used for the SEO title, and the shop description is used for the meta description. The SEO component can be overwritten in other files, such as the product handle. The cart data is obtained using the defer utility from Remix to make streaming data. The cart icon is created using the cart data and displayed in the header component. The cart icon can access data at the component level, which is not possible in Next 12. The suspense and wait functionality allows the page to load and then display the rest of the cart data when it's ready. The cart components include line items and a remove from cart button. The cart line items component displays all the cart line items using a flattened connection component from React Hydrogen.

Ah, I forgot to explain something. SEO. So how to handle SEO. And let me show you that. So in the root file here, we have an SEO component. And we have an export handle. Where is it? Yes, here. We have this export handle and we can create this SEO function and pass the data from the loader into this SEO function. And here for example, we want as SEO title, we want the shop name. So this comes from this query shop. And for our meta description, we want the shop description. Then we place is this SEO component here into the head in the root. And then in the other files, for example, in the product handle, we can overwrite it. So here my SEO, I want here to be the title, to be the product title and the description to be the product description. And if I look at my product here, for example, if I inspect here my, you can see that the title is the title and the description to make a description, it's my description here. So it's makes very easy to handle SEO. Any questions about that? No, for me, no.

Okay. So let's go back here. So yes, what I wanted to show you now here in the root file, we want the data from the cart. But we're going to make something different because we want immediately this data from the shop for SEO. So we don't want to wait from the promise from the cart to be resolved. And for that, we use defer, which is a utility from Remix to make streaming data so it could transport the promise to the UI components and we will resolve them there. So we just wrap with this defer function, the shop and the cart. Okay? And from there, we create the cart icon. So in component cart icon, here we are going to resolve our cart with a weight along with suspense. This is why this cart needs JavaScript, but if I was not using a weight and suspense, I could show you that it works even without JavaScript. But I wanted to show you this function. So I don't know if it's super useful in this case or just the shop SEO, but it's just a way to show it. You can explore it more in documentation. And basically I think this does what streaming with a React Server component that I have not used a lot. I think you can do it without using React Server components. But I know that Remix wants to implement React Server components, but they wait it to be really stable because from what I heard in the next 13, it's not really stable and people that begin to use it are not super happy. Have you experienced with, what can you say, Pieter, about next 13. Well, I read the same comments. I've got a colleague who was a bit mad about it because he thought it was not production-ready. Yeah, but they say it's production-ready. Yeah, but sometimes I feel next release stuff is a little bit too early. Yeah, yeah, yeah. Yeah, so Remix will have it but when it will be stable. And again, I don't work for Remix but I love it.

So, here, using await, we resolve our card and we get data here and from there, we can check the data total quantity and if it's superior to zero, we display it in the icon. So, very simple and then we place our card icon in the header component here. So, card icon is there. Okay, await, so what's saying here, suspense and everything is here. And the icon card, yes, it's just an icon from Rect Icons. Okay and yes here we can use other data because the card icon is a child of the root file. So we can get the data at the component level which is not possible in Next 12 almost, I know. That was another thing that I really didn't like in Next when you have a header, you have to drill props up and down, so I was coming from Gatsby before diving into Remix and this part of Next, I say why, why cannot we do that? So, well, that's how I say my opinions are my own.

So I think that was the cart icon, any question about that? Just a small question, the whole suspense, the wait thing is just how the page loads and then the rest of the cart comes in when it's ready. So if you would- Yeah, basically the cart instead of, careful on this, instead of being resolved here because we want to immediately this data will be resolved in the UI component. So when this component appears, so. So if we have some critical data on the route that we want immediately in the loader then we can defer these promises. That's the purpose of it. Yep. Okay. And don't you need to pass a fallback to the suspense component? Yes, we can do it. I have not done it here. That was just what I was going to say. We can pass here a fallback, here is not really needed but yes, normally you can, you pass a fallback here. Okay, any other question? Yes, we're good. Okay, so now we want, yes, now we can create also cart components. So we have the line items. The line item represent one product and here we render also the remove from cart button. So this is one product. We have the image, the link. So basically this is this, okay? This is one line item. Then on the cart line items, we will display all the cart line items. And here again, we use a component from React Hydrogen as a flattened connection that flatten the node and Hedges object in a simple array of lines.

7. Displaying Cart Data and Explaining useMatches

Short description:

We use a component from React Hydrogen as a flattened connection to display each line item. The cart summaries render the total, and the checkout button links to the checkout URL. We get the cart data using use matches on the cart route. If there are items in the cart, we display the cart content component; otherwise, we display the cart empty component. The use matches hook allows us to access data from the current route and other routes. It provides information about all the routes up to the current one.

And here again, we use a component from React Hydrogen as a flattened connection that flatten the node and Hedges object in a simple array of lines. So we can map around the lines and display each line item. Then we have the cart summaries that render the total when we use the money component here. Then we have the checkout button that links to the checkout URL here. And the cart content display all that.

So the cart line items, the products, the cart summary, and the checkout button. As we can see, okay, here we have the line items, the cart summary, and the checkout button here. And okay, now we have everything. Now we need to display the cart data. So this is on the cart route. And here the cart route is another route, so it's not a child of the root file. So to get the data, we are not going to use user data, but we're going to use use matches, and with use matches, we, ta-da-da, we can get, well first we have this, wait a minute. Oh yes, this is my farm action, that's, okay we are in the component, so yes, with use matches, we get the data from the route, we get the data from all the other routes, and in the root data we have the cart. So from there we get the cart data, and again, we use await and suspense. And if there is items in my cart, I display the cart content component, otherwise I display the cart empty component. And that's it, we have now a cart that works.

Any question about that? We have time, we are going very fast, when I was doing it live ten days ago in Alicante, we have only three people because there was a lot of other workshops at the same time, and it was a full four hours because everybody was going slowly, asking questions, and here online everything goes faster, or perhaps you understand faster than the people I have, I don't know. But it's going really fast. So let me know if you have questions, don't hesitate we have three hours, and I think we will finish really earlier. So don't hesitate to ask questions.

So the use matches, could you explain that a little bit more, because what's the difference between the use loader and use matches, because use loader is used when you use the loader function I guess? Yes you use the loader, but with use loader data you get the data from the parenthroute, but here we have the parenthroute the route is a route five, but here we have created another route, we're on the cart route, okay, so we need the data and so use matches if we go to the remix doc, okay, but I will make a console log in, you will see it. Okay, return the current route matches on the page, ah yes it doesn't explain a lot, but I can show you with console log what it does, so we are on the cart here, and oops, okay, so, can I see it here? Not here, wait, not very good at live coding to be honest. I think it's, I can only see here. So, basically you're here, you see the use matches. You see the data from, from the card shoot and the route that are up in the, in the tree. So if we bring the data out, even array with the route data and, and that's the goal. I cannot see this console though. What I'm going to restart. So, but it gives you the information of all the routes or yes, all the routes that are up to this one. Okay. Okay. Okay. So he doesn't display. For example, I have a route for pages. He would not this place is one, but the route, the route files up in the tree. Okay. The card route is not a child of it. So I cannot get the data from the root fight, but I can find these data. We use matches. Okay. It matches throughout. So yes, something like that. Something like, try to remember that boy. Yeah. Which would be displayed here. Oh, there it is. Here just to understand. So you see, we have an array. We have the route and we have the root card here. You see? Yes. I can route the route data. And from there, yes, I give you that card. I see. Because, because the card is loaded in the route. So yes, from there. Yes, because I have written my loader into it because I need to data globally because I don't see the header. But now that's why I need this matches and it's good because he makes me expect more things. So now it works. Okay. Thanks. Any other questions? No. Let me know. Okay. Are the people. Okay. So now let's go back. Somebody has. Yes, it's the same. Same documentation I have. I put here.

8. Creating a Storyblock Account

Short description:

Now we have all the Shopify product working and want to build. Create an account on Storyblock. Once logged in, click to create a space. Get a local copy, create content, and explore the block library. It's an easy part without code. Everyone quickly understands.

Okay. Now we have all the Shopify product is working and now we want to build. So all right, so we have to create an account. And I'm going to show you how to do that. First. We go to story block. The website. And if you don't have an account, you create an account. And if you have an account, you sign up. So just let me know when everybody is there. And then you just have. Two. So this is a space with all the components. And pages. All the content from there will be clone in your own. Story block space. Everybody. Yeah. No. No. Well. I'm logging into storybook. And it gives me a. And it creates a demo. And that's the one I have to execute. No, no, no, no, no. Just as is link in. Just read my instructions here. Just read box space image with this particular. This is you. Just once you are. You are logged in in your. Story blog account. You just have to click here. And it will create. The space. Hmm. At the, when we click on that link. We have that. That screen that Peter said. Right now. And we need to get a local copy, then create content and. Wait, wait, wait, wait, let me, let me try it. Okay. Right. Okay. Yeah. You know, you have a, you have a, you know, uh, e-mail address. Yes. But look, if you'll go there, you have the content. You have the block library. You have everything. You need. Okay. No worries. Okay. You're good. So it's fun because it's one of the easier part, you know, there is no code in anything. Yes. Everybody understand everything. Quickly. It's difficult. It's not simple for. Can it be that simple? It can not be that. No, no, you have everything there. So, yeah. So next time. Yes. I have to make it more complicated. So.

9. Connecting Storyblok and Adding Development Server

Short description:

To connect Storyblok, get the preview token from the settings API and install the react SDK plugin. Initialize a Storyblok app and pass the access token. Map React components with Storyblok components. Storyblok is component-based. Peter, an agency from the Netherlands, uses Storyblok for e-commerce platforms. They are partners and have good contacts. Add the development server to Storyblok in the settings and visual editor. Set up the connection with the space and add the localhost 3010 as HTTPS.

Okay. So from there. We get the preview token from settings API. So. The. The settings and. No access token. Yes. Yeah. Access to come. So you come on this one. You copy this one. Okay. Yup. And from there. You install your QP, and then you install the react SDK plugin. You have to do that. But you run NPM install to get this. And you initialize a story, block in app. So here you need to pass the access token here in story block. You need, this is the only thing you have to change. So story book, you need set up the connection with the space. And inside the visual editor, and the function also provides an instance of the story block API clients that we can use to retrieve content from story block. So, in the code, I go to my new branch to connect story block, here. And this is in the root file. So, okay. So, we have story block in the API plug-in from the story block React SDK. And in story block here we pass our access token. We have this component that we pass here. And this will map the component that we build in story block. That will be mapped with React components. Okay? And so, this something I really love in story block. It's component-based. So, we really map the React components and the story block components. By the way, somebody has already used story block or it's totally new for you? I didn't ask this. I cannot hear you. We are not new to it. But we haven't used it in the project. Okay. So, I played around with simple tutorial with the features and the basics of story block. So, I know a little bit about it. Okay. Okay. It's recognizable. Okay, good. And Peter, you are independent, you're an agency. What are you doing? Well, we're an agency from the Netherlands, we're called the nieuwe zaak, which roughly translates to the new business. Okay. And we are concentrating on e-commerce platforms. So, we are using Intershop and big commerce to develop web shops for our customers. So, that's our main business. And we're looking into endless possibilities. So, we needed a CMS for that. And Storyblok came up lots of times, so we tried to, we are checking them out. We also did the partner thing and we have a contact here in the Netherlands. Ah, you're already, I was going to talk about that, but you're already a partner. Yes, yes. Okay, cool. Great, great, great. So, yes, so you have really good contacts. Great, great, great. So, yes, so you have really to learn Storyblok in this way. And there is plugins also for BigCommerce and older e-commerce platform, but I think you know that. Yes. Okay, okay. So, now we are connecting Storyblok and now we need to add the development server to Storyblok. So, we go to Settings, Visual Editor and we add this localhost 3010 because we need an HTTPS and we go also to Entry Configuration and add this as readback. So, I show you that. So, here in Visual Editor. Okay.

10. Setting up Environment and Creating Page Routes

Short description:

We have set up the default environment with localhost 3010 and a live environment with Deploy Universal. We configure the entry with the real path as a slash. To enable HTTPS, we add an HTTPS proxy. In VS Code, we can use the Ports option to expose localhost to the public. We can also use a local SSL proxy for HTTPS. We create a splat route for the pages, which maps to any URL not matched by other routes in the same directory.

As default environment, I have localhost 3010. As you can see, I also have a live environment with my live website, which is Deploy Universal. And then on the content and home, we have here the entry configuration. And here you see I had the real path as a slash because we don't want to be the URL-slash-home. The real path is just the root file. So we need always to pass that. Okay? And now, we need to add the https proxy because we need to have the https. So here I just had the link to do it with Windows and if you're on Windows, follow this link. And here I have the explanation to do it on Mac. So you need to do brew install mkaster. Then mkaster install mkaster localhost inside the repo and this will create these two files, okay? And they are on gitignore2. There's a—may I do a small introduction? In VS Code there is an option called Ports and there you can expose your localhost to the public. So that's also a way to—and it's also HTTPS. Okay. Ah, I have to look into that. Yeah, I did it this way, and it's always a little bit of a hassle because you have to make a certificate and stuff like that, but there is a way. You can make it private and public, but then it's exposed to the world, and so it's easy to share your local environment. That's what it's used for, but the nice convenience is that it's also on HTTPS. So it's basically just within Visual Studio Code. It's next to the terminal, if you have that open. Are we looking to it? Yeah, we'll try it for the next time. It works like that? Yeah. So then it starts and runs a proxy. So NPN install glocal SSL proxy, and then each time you run this command, so we have to register here because I use it often, and now... Okay. If I run it here... Okay. Let's see. Now it goes on research GPS, element 10, and here... Okay. I'm going to change the URL for this one, and now we are connected, okay? But for the moment, we have nothing on the homepage because we have not built the component for the moment. Okay. So let me know when you are there with the proxy working and that you can see that in the homepage. Okay. I have a question. I can see my local house. I'm seeing another address, like demo space, so I'm not sure how I can visualize my local. What have you done? Have you cloned the space? Because if you see... because when you create something in Storyblok, let me show you. If we go to Storyblok. So I don't know what you have done but if you have created this add space and create demo space, this is pre-built space and front end to explore everything, all the features. Okay. So if you have done that, that's cool if you want to explore it but not for this workshop, So what you need to do is to just click on this link and you will have the space, the right space. I think that was from... Yes. Perhaps the name is demo space. I don't remember then. You rename it as you want on the settings. So this is a space and you should go to the settings. You know you can name it as you want. But, yes, I think it called it your demo space. You just have to rename it. But then if everything is right, you should have a home with these components and you should have a block library with all that. Okay. And anyway, if it's well done, when you link, you will have all the front end displaying. But, normally, clicking on this link, you will have all this built for you directly. Okay. Yeah, now I got it. OK, good. So next step. Next step, we are going to create the route for the pages. And for that, we have created a splat route. The splat route is like the catch them all in Next. These routes will map to any URL, not matched by other routes filed in the same directory. And so this is very useful, because content editors will be able to create new pages with a nested folder. And we don't need to create other routes for that, for the pages. If you have pages about slash, I don't know, customers or whatever, it will work. Okay? So, we create this route here. Okay. I go here to my Next branch.

11. Using Storyblok and Creating Page Component

Short description:

In my route, I import the Get story block API and retrieve the story from UseLoaderData. The loader retrieves the data from the get story block API using the slug from the params. The useStoryBlockState function loads the JavaScript bridge and allows for the visual editor. The Storyblok component displays the components dynamically and conditionally. The page component has a body field that contains an array of components, which are displayed using the story block component. The story block editable allows for direct editing of components in real time.

And in my route, it's here. So, here, I get... So, I import the Get story block API. There's YouStoryBlockState and StoryBlockComponent from the Storyblok SDK for React. And here, in my route, I get my story from UseLoaderData. Which comes from... Yes, this comes from the route. So, we can go to the route file here. I'm going to say that I'm losing something. Okay. Yes, because my loader is written after. Normally I would write it before. So, here in my loader, I get my data from get story block API, that comes from SDK. I pass here the GET method, the CDN story with the slug. I get the slug from the params here. And here is version draft, and then in my JSON, I return the story, which is a data story, okay? Then I retrieve it here with used loader data, so now you know how it works, the loader, the data. And I pass it in the function useStoryBlockState, and this will load the JavaScript bridge and listen to the events on the visual editor. So thanks to that, we can have the visual editor. And then this Storyblok component will display dynamically and conditionally the components if they exist. And here we pass in the block property the story content. So if we are in Storyblok, let me show you. Here we have the JSON, and you can see we have a story, created that, id, etc. And you have the content. And here we have a body component, but I'm going to explain. Peter, I hear all the noise around so if you can mute now. So, REMIX by definition, needs an index.jsx file inside the root directory. So, the problem is that this will collide with the root of our home page so as we don't want to repeat the code from our dynamic root, we can replace the code of the index.jsx files like this. And now we're going to build the page component. So in the component, I create the folder block in components. There's two ways of doing it. It's not something mandatory, but it organizes things better because I know in blocks, these are the components that are mapped to story block. And here, I import story block editable and story block components. So story block editable, thanks to that, as you can see, I have to reload normally. And you're going to see everything. No, what happened? OK, I only have the page components here. OK, so for the moment, I just display the page here, but I have nothing inside for the moment. So in my page, as you can see, I have a body field. OK, and this body field, it's made with a field type named block and this type of block, as you can see, we have many types of block text, text area, rich text, markdown, all the common field types, but we have some special field types. We have the blocks and the plugin, and we're going to explore them. So the block field you can nest in all other components inside of it. So this what makes this atomic design principles. You can nest components inside one another, but you can also allow minimum or maximum number of components, and we can allow only specific components to be inserted. So here, all the components are allowed, but we could make a folder with only certain components and only allow this one, or we will see later. Other blocks fields where we allow only certain types of components. So, if we look again at our draft here, we can see this body field, and in this body field, we see our other components, what I have named variants that we're going to explore later. But as it's a block field, we have several components. We have an array of components inside of it. And that's why we have, again, this block body map. And again, we use a story block component to display dynamically the components that are inside this body field. Okay. And the story block editable makes it when we click on a component, it's directly editable. Like that, let me show you if I go to the live URL. Here, you can see I can edit everything. And in real time, just by clicking on it, which is very nice in my opinion. And not only because I work for them. So this is for the page component. And then this component, I bring it here in the root file, I important it here, okay? And I pass it and map it in my component object to the page component, okay?

12. Personalizing Homepage with User Behavior

Short description:

Storyblok editable allows marking React components as editable for easy customization. Next, we personalize the homepage based on user behavior by storing collection info in a cookie. The banner component is created and can be customized in the back office. Editors can choose products from Shopify and customize layouts and CSS. The personalized banner and personalized products components are used to display the personalized content.

Okay, but you know already Storyblok so perhaps people who have never seen it have more questions, I don't know. Okay. Okay, so yes, I have more explanation, so Storyblok editable, this function allows us to mark the React component as editable so when we load the page that's contained inside the visual editor, you will be able to click it and edit its properties and we mark all the React component that lead to Storyblok components as editable. Okay. So now we go to the next branch, the personalized component. Okay. So I think I made a mistake. It's not branch. Yes, it's branch six. Okay. So we are going to personalize the homepage based on the user behavior. So if a user visits a specific collection like performance board, they'll see a matching banner and project read on the homepage. So we store the collection info in a cookie by using react-use-cookie. So you need to run NPM install because I have this new component. Yes. I cannot hear you. I cannot hear you. You still, you're still muted. You need to unmute. I cannot hear you. Yes. No problem. Some colleagues are leaving the building, so it's no pay here. So I have to wave them goodbye. They were wondering why am I still so late, so. Okay, I was thinking you were asking. No question, no question. Okay, okay, so you can mute again. So we installed the package, NPM install react-use-cookie and in the collection handle, we import get cookie and set cookie from react-use-cookie. And here, so we are going to store the collection handle so if there is no user type and there is a collection, we send the cookie to, we name it userType, and we take the collection handle as value for this cookie. And so we can see it in the website here. If we go to application and the cookie, you can see that the user type is performance board here, okay. And if I go to the board and I go to this one, now I see it has changed to original boards, okay. And when I go home here, I have now my original boards banner. Okay? So it's very simple. It's very simple for this case. I mean, you can make a much more as and set personalization. This is the principle of how it works. I think now you can, yes, use external applications, AI to do in this field, but this is the basic thing. So, okay, so let's go in my collection handle. It's, it's here. Okay, so very simple. Then we create the banner component. So I'm going to show you how we works in the back office before that. So here we can see that in our body, we have personalized banner and personalized products, and we have single product. So this single product, as you can see, I can create here another product. I create a single product here and you see, I have already my button and here I can choose my product. So it goes to pull that from Shopify, so for example, I choose this one. And you see I can choose only one because I have limited to one. You can see everything appears in real time. And Remix is server-side also, so everything goes directly to live here. And like that, I have my description. Oops, and my AirPods are going away. And I can reverse the layout also if I want. So, okay, this triggers some CSS. It's not magical, it's not inside the component. So, how this is, so this is the part that the editors will see. If you have a content team, they will use only that. And here in the personalized banner, I have three banners components. They have a component name variance that will contain three banners. And if I inspect this component, I see it's again a block field. But here I have only allowed banners component to be inserted. Okay. So, oops. Let's do another one. You see, I can have other banners here. Okay, if I go to the page. Okay, banners. And it's the same thing for the personalized read. We have pre-variance and here the variant has to be a private read.

13. Shopify Components and Data Mapping

Short description:

We have pre-variance and here the variant has to be a private read. In the back office, the simple ones, the banner one, have the schema, title text, and the user type. The personalized banner and personalized grid have a block field named variant. The single product has a headline, description, layout, and a product type field. To connect the Shopify plugin, the SB Shopify option is chosen from the dropdown list, and the endpoint and tokens from Shopify are connected. The user type and product fields are used in the product read. The missing data from the plugin is obtained by querying all the products. The single product component retrieves the necessary data to build the product. The plugin pulls data from Shopify but not all the data, so additional data is obtained and mapped. Loading too much data may be an issue, especially with a large number of products.

We have pre-variance and here the variant has to be a private read. Now, if I inspect my banners. I can see I have a field for title, for text and for the image, but I have also a user type field and by default is empty. But here I have another component which has the original user type and here's the image and the title and content are different and here I have a performance user type and same principal for the personalized grid. I have the products I can choose here and I have a user type which is empty by default and I have two other components which has a performance user type and original user type.

Okay. So, now let's see how these, like, these blocks are built. So the simple ones, the banner one, we have the schema, title text and the user type which is a single option field and okay, the personalized banner, as I was saying, it's a block field name variant, same thing for the personalized grid and with a limitation to allow only specific components. Let's see the single product. So, in the single product, we have a headline, a description and a layout, say if we want left or right and we have another field which is a product type field, a product, no, a plugin type field and we have named it product. So, if I open it here, so, Storyblok, it's extendable and we can build any plugin as soon as you have an API, you can build a plugin, but this one, the Shopify one, BigCommerce and other platforms are available and pre-built for you on certain plans, so the Teams plan for Shopify and Enterprise plan for Storyblok and other ones. But you can also build your own plugins extensions if you use a platform that we have not created the plugin. So, to connect it, we use here in the dropdown list, we choose SB Shopify, and we connect here the endpoint and tokens that you get from Shopify, and here I have limited to one product and select only product. We could also choose category here, but here it's for product. So this is for the single product, and for the product read is the same principle, we have the user type, and we have the product but here we have a limit to four products. Okay, so this is how it works in the back office. And now in the code, so we continue here. So we have stored the user-type cookie, which is the collection handle, and now we create the banner component. And in this banner component, Okay, this is very simple because we get from the blog, the user types, the UID, the titles of the text and the image, and we pass StoryblockEditable, and then we have all the data to build our banner with the JSX and Tailwind. And here we pass the user type in the link to, so it will link to the right collection. So if it's original board, it will be collection slash original boards. Okay. So this is for the banners. And now we create a personalized banner component. So here we import get cookie, and we create the user type by getting the cookie with get cookie. And then we get the variant by filtering the block variants. So we choose one which has the same user type. And from there, we map, there is only one variant, but it's an array. So we need to use again, a map function and use Storyblok component. And from there, it will display the right banner or the right, or the right product tree depending on the navigation from the user if you have visited the performance board or the original board. And then we need to pass all these components to Storyblok init in the root file, okay?

Any question? No, nope. Okay all the people, all good? Mirko, have you finally, solved Thomas? Yeah, yeah, yeah. Yeah, Thomas, yes? The problem was just run the yarn dev command because I shut down before when I install the dependencies and now I run a yarn dev and then I run back local host the command one. Okay, so it works now? Yeah, yeah. Okay, great. Okay, great. So here, if I go to the... Okay here, I just made the banners in this branch. So now, okay, we are going to create the Shopify components in the code. So we go to the branch seven Shopify components. Okay. So here, I created Shopify folder into the blocks one. This is my way of doing thing. Again, you can make it different, but I think it's handy. And, oops. So here, I create the single product. Okay. So I get from the blocks your UID, the headlines, the layout, the description and the products that I rename here as the product. Because I'm going to show you, I don't have all the data I need from Storyblok. So from Storyblok, if I go here, okay, I have my product field here, my product component and I have my items inside, well, only one item. And from there, I get the IDs, the names, the types, the image, but this image is small, it's 140 so I don't want to use this one and the description, but I want to link this product so I need the handle and I need a bigger image. So I need to map it with all the products. So for that, I didn't do it the better way, I have to correct that because for that, what I have done in the page root, in the splatch root here, I have query all all the products. I think we can query only the right one with a variable but for the moment I have done it like that, I have to correct that and so from there, I get all my products in my in my loader here. Okay so here products start from query products query and I return it here products nodes in my return from my loader. So from there in my single product, I can get all the products from used loader data. And then I find a filter the product that has the same ID because both have an ID. So it gives us a parameter to filter and to get the product that corresponds to this one. And from there, I get the handle and variance and I get my image from there. And from there, I have all the data to build my single product here. Okay. Any question about that? So it's just because you're missing the data from the plugin? It's not giving you all the data? Yes. The plugin pulls data from Shopify but not all the data. So we need to get the missing data and to map things with that. But I think, yes, I need to do it in another way because I'm loading too much data. More, it's not the live website, it's a demonstration. No, no, no, no. I understand, I understand. But with 10,000 products it will not work, I think, I guess? Yes! No, no. I know it is, that's why I say it and yeah.

14. Using Storyblok and Personalized Grid

Short description:

Thank you for the demo. We pass the component to Storyblok Init, including the ProductGrid. We get all products, filter them by ID, and display the product grid with the buy button. In the personalized grid, we filter the variance and display the components accordingly. We appreciate your feedback.

It's a good demo, so thank you. Thank you. Okay. So you will fix it, I'm sure. So yeah. Okay. Okay, so this is here. And of course we pass this component to Storyblok Init. Same principle with the ProductGrid. We get again all products. So, okay. I guess it's my products from the block and all of the products. And then I map around my Storyblok products and here I filter it again by ID. And then I get all my data to display my product grid with even the buy button of the product. I'm not surprised, I didn't put a button to buy it, but I could, yes, I had the add to cart button also so we can directly add to cart here. So, and then I pass it again to the route here. So now I have all my components from Storyblok here. Okay, and then in the personalized grid again, I get the cookie, so the user type, and I filter my variance same way, like for the personalized banner. And then I map around my components and display the right one. And that's all and voila, we have everything. So, thank you. So let me know if you have more questions, critics also please tell me like this workshop, if I can improve. I really appreciate your feedback. Well, thank you very much. It was very insightful.

15. Integrating Storyblok with Product Detail Page

Short description:

I'm still looking at integrating Storyblok with the product detail page. The challenge is that the page already exists outside of Storyblok, but I want to add Storyblok components to it. For example, I want to add a banner to the product detail page. It's a bit tricky to figure out the best approach. We could work the other way around and feed Storyblok with all the product pages, but that would be complicated due to the dynamic nature of the product handle.

Right. I'm still looking at a problem we have integrating Storyblok with a for instance, your product detail page, because there's a route that's already there. It's not living in Storyblok. You want to integrate Storyblok components on the product and it needs to be on that page only. So it's quite difficult to wrap my head around how to do that.

What's explain better? So you have a route which has products and you want them to display individually using the Shopify plugin or something like that? Yeah. Well, for instance, you're on a product detail page, you use selected a dashboard and you're going on that page. So that page lives, does not live in Storyblok. And so, there's no page for that but I do want to put Storyblok components on that page. So for instance, I want a banner on the product detail page. But that page does not exist in Storyblok.

Okay, yes, you mean that if it's like if I was here, okay, and that I want to display a banner, right? Yeah, which customers placed on that specific product. So you need. Yes, you made the opposite because here we have a Storyblok page and we display, we pull things from Shopify and we display and here you want the opposite. I have to think about it. Oh! Maybe we should work the other way around, but then you have to feed Storyblok with all the product pages. Yes, it would be complicated because this is dynamic, we made the product handle.

16. Integrating Storyblok and Product Handle

Short description:

I need to insert a component here to get data from Storyblok in Remix. I can retrieve the data using the get Storyblok API in my product handle. However, making it editable in the visual editor would be a problem. Another solution could be creating a page that dynamically loads the product handle data from Shopify. It's an interesting problem because BigCommerce has a similar feature in their CMS. We want to bring back that functionality when going headless.

Yeah. So I think it's the right way. So we need to insert a component here. I'm sure it's not so complicated, but after two hours doing the workshop, my brain is not working so fast. So let's say, but of course I'm on Remix. So I need, I'm on this route and I need a banner. So I need to get data from Storyblok here. So in Remix, so in next, I think this will happen on the static props or something like that. Here it would be in the handle. We need to, yes. We need to load the data in the handle here. But effectively, I don't know if it would be editable in Storyblok in this case. That's the thing. What do you mean? So, I need, okay, I have my loader. So yeah, you need to get the data there from Storyblok. So here I should do like I do. I should, here, for example, okay. I should use the get Storyblok API. And get this banner in my product handle. And once I have it, so here in my loader, and in that case it would be on get static crops, I think. Then I can display it on my page. But I don't think it would be editable. You will see it in the visual editor, but I don't know if you can edit it directly in the visual editor. But, yes, sure. I could retrieve the data, so that would not be a problem. But making it editable, so that would be a problem. Yes, that's a problem. Yeah. Yeah. OK. That's an interesting question. That would explain why my application. Yeah. OK. That's an answer also. OK. Or I'm thinking can we introduce a product in a page, in this case, doing products page and loading the data for products inside the page. But making it a page, making a Storyblok component, but loading the data from the page. Not with the plugin, but with Shopify directly. And then I'm just thinking of now. Yeah. Yeah. But yes, perhaps making a page that contains dynamically the product handle. I don't know. Something like that. But I think, yes, you have to be inside the page in this case. But it's an interesting problem. Basically, it's because BigCommerce has that feature in their existing CMS. So you can go to a detail page and put little widgets on that specific product. So it's always a customer. Yeah, but we already have that. So we want it back when we go headless. And that's the story behind that. Yes. No, but it's interesting. It's interesting. So yeah, yeah, yeah, yeah. Because yes, what happened at DevRel is we build this demo, but it's all by building projects myself for clients, if I have said projects, or by seeing partners having use cases that we see the real cases and what we can do when we think about things. Because there is so many manners to use something that you cannot think about everything. So it's an interesting problem. Yeah. Our clients always surprise us with little things like that.

17. Closing Remarks and Farewell

Short description:

Anything else? I'm here for another hour. Thanks to you and Peter for being the face of the workshop. I'm a talkative, extroverted developer. Have a nice evening and enjoy building with hydrogen. Thank you.

Okay. Okay. Anything else, the other people, if you have questions, feedback, whatever? I'm here before I left. We still have one hour if you can ask me anything. Well, I have to get home.

Okay, okay. For the time of the workshop, we still have one hour. Yeah, well, thanks a lot. Thanks to you and thanks, Peter, to be the face and the talking person for me because I really don't like it when it's three in the void. So it was really nice to meet you. I'm a weird developer, I like to talk. Yes, like me, like me. I'm a super talkative, super extrovert. And I don't drink coffee. I don't like puzzles. I'm really, I'm a creative. So, yeah, I don't like having the developers, because knowing all that.

OK, so have a nice evening. And I hope that you will build, for you it's true, but for the other people that you will use it and build things with hydrogen. Thank you, thank you. Thank you. Thank you.

Watch more workshops on topic

React Summit 2022React Summit 2022
136 min
Remix Fundamentals
Featured WorkshopFree
Building modern web applications is riddled with complexity And that's only if you bother to deal with the problems
Tired of wiring up onSubmit to backend APIs and making sure your client-side cache stays up-to-date? Wouldn't it be cool to be able to use the global nature of CSS to your benefit, rather than find tools or conventions to avoid or work around it? And how would you like nested layouts with intelligent and performance optimized data management that just works™?
Remix solves some of these problems, and completely eliminates the rest. You don't even have to think about server cache management or global CSS namespace clashes. It's not that Remix has APIs to avoid these problems, they simply don't exist when you're using Remix. Oh, and you don't need that huge complex graphql client when you're using Remix. They've got you covered. Ready to build faster apps faster?
At the end of this workshop, you'll know how to:
- Create Remix Routes
- Style Remix applications
- Load data in Remix loaders
- Mutate data with forms and actions
React Summit 2023React Summit 2023
106 min
Back to the Roots With Remix
Featured Workshop
The modern web would be different without rich client-side applications supported by powerful frameworks: React, Angular, Vue, Lit, and many others. These frameworks rely on client-side JavaScript, which is their core. However, there are other approaches to rendering. One of them (quite old, by the way) is server-side rendering entirely without JavaScript. Let's find out if this is a good idea and how Remix can help us with it?
- Good understanding of JavaScript or TypeScript
- It would help to have experience with React, Redux, Node.js and writing FrontEnd and BackEnd applications
Preinstall Node.js, npm
- We prefer to use VSCode, but also cloud IDEs such as
(other IDEs are also ok)
Remix Conf Europe 2022Remix Conf Europe 2022
195 min
How to Solve Real-World Problems with Remix
Featured Workshop
- Errors? How to render and log your server and client errors
a - When to return errors vs throw
b - Setup logging service like Sentry, LogRocket, and Bugsnag
- Forms? How to validate and handle multi-page forms
a - Use zod to validate form data in your action
b - Step through multi-page forms without losing data
- Stuck? How to patch bugs or missing features in Remix so you can move on
a - Use patch-package to quickly fix your Remix install
b - Show tool for managing multiple patches and cherry-pick open PRs
- Users? How to handle multi-tenant apps with Prisma
a - Determine tenant by host or by user
b - Multiple database or single database/multiple schemas
c - Ensures tenant data always separate from others
Remix Conf Europe 2022Remix Conf Europe 2022
156 min
Build and Launch a personal blog using Remix and Vercel
Featured Workshop
In this workshop we will learn how to build a personal blog from scratch using Remix, TailwindCSS. The blog will be hosted on Vercel and all the content will be dynamically served from a separate GitHub repository. We will be using HTTP Caching for the blog posts.
What we want to achieve at the end of the workshop is to have a list of our blog posts displayed on the deployed version of the website, the ability to filter them and to read them individually.
Table of contents: 
- Setup a Remix Project with a predefined stack
- Install additional dependencies
- Read content from GiHub
- Display Content from GitHub
- Parse the content and load it within our app using mdx-bundler
- Create separate blog post page to have them displayed standalone
- Add filters on the initial list of blog posts
React Summit Remote Edition 2021React Summit Remote Edition 2021
87 min
Building a Shopify App with React & Node
Shopify merchants have a diverse set of needs, and developers have a unique opportunity to meet those needs building apps. Building an app can be tough work but Shopify has created a set of tools and resources to help you build out a seamless app experience as quickly as possible. Get hands on experience building an embedded Shopify app using the Shopify App CLI, Polaris and Shopify App Bridge.
We’ll show you how to create an app that accesses information from a development store and can run in your local environment.

React Summit 2023React Summit 2023
139 min
Create a Visually Editable Next.js Website Using React Bricks, With Blog and E-commerce
- React Bricks: why we built it, what it is and how it works
- Create a free account
- Create a new project with Next.js and Tailwind
- Explore the directory structure
- Anatomy of a Brick
- Create a new Brick (Text-Image)
- Add a title and description with RichText visual editing
- Add an Image with visual editing
- Add Sidebar controls to edit props (padding and image side)
- Nesting Bricks using the Repeater component
- Create an Image gallery brick
- Publish on Netlify or Vercel
- Page Types and Custom fields
- Access Page meta values
- Internationalization
- How to reuse content across pages: Stories and Embeds
- How to create an E-commerce with Products’ data from an external database and landing pages created visually in React Bricks
- Advanced enterprise features: flexible permissions, locked structure, custom visual components

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Summit Remote Edition 2021React Summit Remote Edition 2021
33 min
Building Better Websites with Remix
Remix is a new web framework from the creators of React Router that helps you build better, faster websites through a solid understanding of web fundamentals. Remix takes care of the heavy lifting like server rendering, code splitting, prefetching, and navigation and leaves you with the fun part: building something awesome!
React Advanced Conference 2021React Advanced Conference 2021
39 min
Don't Solve Problems, Eliminate Them
Humans are natural problem solvers and we're good enough at it that we've survived over the centuries and become the dominant species of the planet. Because we're so good at it, we sometimes become problem seekers too–looking for problems we can solve. Those who most successfully accomplish their goals are the problem eliminators. Let's talk about the distinction between solving and eliminating problems with examples from inside and outside the coding world.

Remix Conf Europe 2022Remix Conf Europe 2022
23 min
Scaling Up with Remix and Micro Frontends
Do you have a large product built by many teams? Are you struggling to release often? Did your frontend turn into a massive unmaintainable monolith? If, like me, you’ve answered yes to any of those questions, this talk is for you! I’ll show you exactly how you can build a micro frontend architecture with Remix to solve those challenges.
Remix Conf Europe 2022Remix Conf Europe 2022
37 min
Full Stack Components
Remix is a web framework that gives you the simple mental model of a Multi-Page App (MPA) but the power and capabilities of a Single-Page App (SPA). One of the big challenges of SPAs is network management resulting in a great deal of indirection and buggy code. This is especially noticeable in application state which Remix completely eliminates, but it's also an issue in individual components that communicate with a single-purpose backend endpoint (like a combobox search for example).
In this talk, Kent will demonstrate how Remix enables you to build complex UI components that are connected to a backend in the simplest and most powerful way you've ever seen. Leaving you time to chill with your family or whatever else you do for fun.
Node Congress 2022Node Congress 2022
34 min
Server-side Auth with Remix, Prisma, and the Web Platform
In this talk, we'll get a live coded demo of building custom hand-rolled authentication. When you have the right tools (and we do), authentication can be quite simple and secure. This is more (and better) than just: "Install this library and you're good to go." When we're done we'll have our own auth code that can evolve with our ever-changing requirements without a need to learn some library-specific APIs. We'll be leveraging the Web Platform the way it was meant to be done to give us simple and secure server-side authentication for the web.
You can check the slides for Kent's talk 
 as well as 
demo code