Get hands on with Hydrogen, a React-based framework for building headless storefronts. Hydrogen is built for Shopify commerce with all the features you need for a production-ready storefront. It provides a quick start, build-fast environment so you can focus on the fun stuff - building unique commerce experiences. In this workshop we’ll scaffold a new storefront and rapidly build a product page. We’ll cover how to get started, file-based routing, fetching data from the Storefront API, Hydrogen’s built-in components and how to apply styling with Tailwind.
You will know:
- Get started with the hello-world template on StackBlitz
- File-based routing to create a /products/example route
- Dynamic routing /products/:handle
- Hit the Storefront API with GraphQL
- Move the query into the Hydrogen app
- Update the query to fetch a product by handle
- Display title, price, image & description.
- Tailwind styling
- Variant picker and buy now button
- Bonus if there’s time: Collections page
Prerequisites:
- A Chromium-based browser (StackBlitz)
- Ideally experience with React. A general web development background would be fine.
Transcription
A good Global representation here. So without much further Ado. I will hand it over to David David wheat is a developer advocate here at Shopify. He's going to work us through getting started with a hydrogen how to build up product page and then the last 30 minutes of this 90 minute session will be for questions and answers and he's going to do this with his fellow teammates from Shopify. So David over to you and all the best. All right. Thank you. Mercy, so welcome everyone. Welcome to this Workshop. Thank you for joining me today. My name is David Witt and I'm joining you from Sunny Seattle Washington. If you're not aware, my state is currently on fire. So the air quality is really bad and it's affected my voice a little bit. So I apologize if my voice goes in and out of it. I'm gonna try and talk a little bit of a lower register, but hopefully I can make it through this hour with me today. We have Brett we have Daniel and we have Matt who are part of the hydrogen team and they'll be Fielding the Q&A at the end of this Workshop. But we're gonna start with 60 Minutes of an interactive Workshop where we together build a product display page. So let's get started. It's a little bit about me. My name is David Witt and I'm a developer Advocate with Shopify. I've been with Shopify since the end of July. So I'm relatively new but I've been working on learning hydrogen and I'm really excited to teach hydrogen to developers like yourselves today. Pictured here is me with my dog Lucy. She's sitting on the couch and I'm sitting on the floor and to her that is the rightful place of where things should be. So if you can relate to that send me a pet pic over to my Twitter handle. I'd love to see and share cupcakes with you. So let's talk about the workshop. Today we're going to be building a product display page in hydrogen and we'll talk about what hydrogen is and how it fits into the Shopify ecosystem. But this is just a preview where we're going to end up today. So all of this data is stored within Shopify and we're going to use an API to query that data and build a custom website where we can interact with it and buy a product which will take us to Shopify check out. So, let's Dive In. If you want to follow along head on over to this URL Shopify Dot github.io/workshops. These workshops will be available after the event too. So if you just like to listen and follow along as I do this, that's fine. You can try doing it in your own time, or if you do want to follow along you can go at your own pace and catch up at any point. I'll try and paste this out so you should be able to follow along but I understand that there's a lot of information coming to all at once. So it is okay to take step back and do this in your own time. So I'm going to exit out of this and switch on over to my workshop page. And in the workshop page, we'll see that we have a bunch of different workshops that are available. I encourage you to explore those within your own time. There's a lot of interesting stuff that we're trying to teach and this is a new method that we're going about teaching. So, please let us know what you think of this but the workshop will be starting with is the create a product page with hydrogen Workshop. So I'll click Start. And we're going to start at step one. So we'll take a step back and just talk about custom storefronts for a moment. So when you think of Shopify most people think of the headed solution where a user signs up for an account, they're able to select a theme and select some apps and configure some Styles and markup and then Shopify serves them that storefront. That's one way to use Shopify and it's great because it provides a lot of structure and you get a lot of really nice things out of the box. But we wanted to provide an option for something that might break outside that box, or maybe you just want to bring your own head to an api-based storefront. And so custom storefronts allow you to do that. So hydrogen is really just shopifies opinionated way of building one of those custom storefronts. So we'll talk a little bit more about what hydrogen is in just a moment, but I want to get everyone started with the project that will be working on which is a stackblitz project. So in step one if you click on this link, That will open up a stack Blitz project for you. And then up in the top left corner. If you click on the fork button that will give you your own instance of this starter project. So over in the right hand side. I'll see that my booting web container is stuck. So if I refresh my page That should get me unstuck and I should be able to see that the start command runs and I'll see a preview of my app over here. So if you're not familiar with stack Blitz, it's a code editor that serves everything from within a web browser. So it's a really nice way for you to play around with hydrogen and get started with just click of a button. So over in the left-hand panel, we have a file explorer. The center panel is going to be our code editor down at the bottom. We have a terminal and on the right hand side. We have our preview window. So it's everything that we need to get started and build with hydrogen. So I'll pop back over to the workshop and just talk a little bit about hydrogen. So as I mentioned hydrogen's shopifies opinionated way of building a custom storefront and it's designed to be a great developer experience, but it's also designed to make your sites really fast and under the hood. It's using react server components which allow for using components but on the server and on the client and it provides streaming server-side rendering Hydrogens also really fast and that you can run it at Edge servers. So you get a really fast time to first fight. Hydrogen is great because it comes built with a lot of components and tools that make developing really fast and really efficient and we'll explore some of those tools in this Workshop. So I'm going to head back over to my stack Blitz project. And the first thing I'll do is just show a couple of configuration pieces that get our storefront started. So I'm going to open hydrogen Dot config.js and this is going to be where I configure which storefront my project is referencing. So this is kind of how we set up our API. So I just specify the domain a storefront token and an API version and for our purposes today. We just have a demo store Workshop where we'll be querying data from So once this configuration is defined it is consumed over an app.server.jsx. Which is going to be kind of the core root component of our app. And so you'll see that our entire app is wrapped in a Shopify provider component and that provider component is going to consume the config file and then give us hooks so that we can query the storefront API so that abstract some of the some of the Pieces away from us and gives us a nice interface using the provider and hook paradigm. So I'm going to move us along to step two and we're and we're going to talk about file based routing. So hydrogen uses file based routing and if you've used next JS or next JS or some of the other popular Frameworks out there, you might be familiar with how this works. But basically it is a nice way to set up a site and to set up your url routing. So it's very similar to a file browser tree. So we're going to create a product display page. So we're going to create a folder for slash products and then we're going to create a file for slash. Whatever our product name is. And so that brings me to the first point. I want to bring up about hydrogen and react server components and that's the concept of where you want your component to render. And so we use a simple naming convention to help us understand and to help key the framework on where these components should render. So a file ending in dot server.jsx will render on the server dot client.jsx will be around on the client and Dot jsx will run on either the server or the client and that will depend on where that file is included and rendered. When there are certain rules that go along with the siding if you want to use a server or a client component, but I'll only mention two rules that we need to worry about for the purposes of this project. So the first one is that all of our file all of our route based file components those need to be server components and then anything that's going to manage user State should be a client component and there's more information on some of the the rules and guidelines and best practices on the shopify.dev website. So let's create our first static route. So back over in stack Blitz. I'm going to open the routes folder and I see that I already have my index server.jsx, which is rendering hello world. I'm going to create a new folder called products. And inside the products folder. I'll create a new file called example.server.jsx. And so this is going to be a react component. So I'm going to export default function example. And I'm just going to return some jsx. So this is going to be a hello example. Just to give us something that's a little bit different from Hello World. When I hit save this is going to register my app with or register my route with my app. So I'm able to navigate to it immediately. So I'm going to come over to my preview window and go to slash products slash example. And we'll see that I now have my hello example component being rendered as a page. So that's great. We have a really simple way of setting up a static route. So static routes are great when you know what that full URL is going to be so slash about us slash FAQs or slash cart. That's a good instance of using a static route. Because we're building a product display page. We're going to want a dynamic route. So we're going to want slash products slash whatever our product handle is and that's gonna be different for each product page. So we don't want to create a new component for each product handle. That would be a little silly. So instead we can use a dynamic route in order to make all of those products be rendered within a single component. So let's convert our example component into a dynamic route now and I can do that by renaming the file. So instead of being example dot server.jsx. I can open up square brackets and make this handle Dot server.jsx and that will register this file as a dynamic route. So I can look over my preview window and still see Hello example, but if I change my route to say hello example one I'll see that it's still rendering the example component or example two still rendering example, so that kind of shows and proves that we now have a dynamic route and anything under the slash products URL test or URL fragment is going to be rendered by this component. So one of the things we'll need to do when we actually interface with our storefront is we'll need to make an API call and we'll pass this handle over to our server to make sure we get the right product and so we can extract that handle from the URL relatively easily because our server component is packed. It passed in a few props that we can use. So we're going to grab the params prop from our route component. And then from that Paramus crop, I'm just going to destructure the handle property. And so then let me print this out to the page just to make sure that we have this, correct. Okay, so over my preview I now see example 2 and I'm going to go back to my original example and we'll see that we have the handle. So that's a nice and easy way for us to grab that handle and then in the next few steps, we'll talk about how to make those storefront API queries. So the next thing I'm going to do is I'm just going to make things look a little bit nicer by importing in a layout component and that's already built for us in our components folder. I'm going to grab it as layout dot server. And then I'm just going to wrap everything. I have so far in my layout component. Okay. So now I see a nice little header and that has set me up for Success here. I did want to go over one instance of breaking the server and so I'm gonna introduce a syntax error and hit save and that's actually going to break my server. So we'll see that I can't refresh anything anymore. And so if you run into that you can usually use undo to get back to where you were before or if you know your error and you can actually see, you know, some of the the code that spit out will help you find the error you can go ahead and fix your error. I'll hit save and then down in my terminal. I can just hit the up Arrow to run to show me the previously run command, which is npm install and yarn beat and I can hit enter and that will re-run my server for me and bring me back to where I was before. So I'm going to go back to slash products slash example, and I'm back to where I was. So if at any point you accidentally introduce an error that's going to be how you get your server back up and running. So that takes us to the end of step two. We have a few steps where if you get stuck along the way we've provided a full code block at the bottom of the step and you should be able to copy the entire code block over to your clipboard paste it into stack Blitz and you should be back on track. So next up we're going to take a step away from our stackblitz project and talk about the storefront API. So Shopify storeprint API is a graphql API that's developed by Shopify and helps to support building of custom storefronts. And so one of the nice things that hydrogen does for us is it provides us with a tool so that we can test and make graphql queries using a browser tool called graphical. So I'll show what that looks like now. Back over and stack Blitz. I see up in the top right corner. I have a button to open our project in a new tab, and I'm going to do that. and what I want to do is I want to go to the host URL and then slash graphical which is g r a p h i q l and that will open up the graphical interface. So if you're not familiar with graphql, I'll make a couple of sample queries and that will hopefully give you an idea of how we can use graphql to query for data. So this interface here is pretty common for graphql interfaces where the left hand side will be where we write our query and the right hand side will be where we see the results of our query. So I'm going to get rid of these comments for now and let's just make a simple query. So we're going to all our query shop and then to figure out how to start my query. I can open the documentation and click on the query route and see what I can query for at the top level. And this is a lot of good information and it's all strongly typed. So it's really helpful. I could also start typing and I have autocomplete that's available to me. So I'm going to query for some basic shop data where inside of the shop I can look for the ID. I can look for the name and we'll just say the description. And I'll hit Ctrl enter or this pink play button to start my query. And we'll see over in the right hand side that I have a data object that kind of matches the shape of the query I have over here. And so that's one of the really nice things about graphql is it kind of gives you a hint at what the shape of your data will look like when you build your query so that's just a really simple example of how to query data and what the shape of that data will be. So let's get rid of this and let's actually focus on product data. I'm going to call this query product details and inside of my product details query. Let's just look for some products. So I see that I have a couple of different product options. I could use I'm going to use products plural which gives us a product connection and I'm just going to start by looking for the first 10 products. And so this is how you specify which products you want to look for. And so this is going to give me a child object of edges and on each one of those edges. I want a node. And so if you're not familiar with that terminology, that's just graph data structure terminology. I won't go into that but the autocomplete will help you to figure out where you need to dive in to get to that actual product data. So for a product inside of my node, let's just get the ID. the handle and the title So thank you autocomplete. I'll hit control enter. And I should now see that I have an edges array where each node is going to represent a product. So I see quite a few that I can reference and for the purposes of this demo. I'm going to be using snowboard as my handle. So I'm going to copy snowboard to my clipboard and I'm now going to rewrite this query so that we can focus on just a single product. So I'll get rid of everything I have so far. And just type in product and when I open up my parentheses, I see that I can query a product by ID or by handle. So I'm going to make it by handle because I know that in our app. We already have the handle from the URL. So we're going to make sure that this is the snowboard handle. And I now have access to the product data. So again, I can do ID title. And what candle and then we'll just say description. So if I run that I should now see that I have a single product data and that'll be nested inside of the product object. So this is great. We're getting much closer to what we would use inside of our app. The only thing we need to do now is make this Dynamic. So rather than having a hard coded snowboard handle, I'm going to extract that from my query and I'm going to instead create a query parameter or graphql and I can do that by setting this up much like I would for ajs function. So I'll put the top of my query name. I can define a new parameter by using the dollar sign syntax and then specifying a tight. So I'm going to make this a string and then I'm going to add an exclamation mark to make it mandatory. And then inside of my query itself, I can use the dollar sign syntax again to reference that variable. So now we've made this dynamic. So if I go ahead and click play now, I should see an error because I haven't actually specified a handle or a queries. And so we do get the expected errors that give us an explanation and can help us to correct this by making sure that we pass in a variable of handle. So I can do that inside of graphql. I'm sorry graphical by opening up the variables tab. And this variables tab at the bottom expects a Json input. So I'll create an object and I can just start typing handle because that's what it expects and then I can paste in the snowboard handle from my clipboard. So if I run this query again, I should now see that I have the same data that I had before and we have success. So this will be the query that we use to render the data on our product display page. So that was just a really quick primer and how to use graphical and graphical comes bundled with hydrogen and it's also got all the configuration set up for you. So it knows which storefront to query and you don't really have to worry about it. So really nice developer experience to get you building your sites quickly. So if you've been following along so far, we'll be at the bottom of step three. And we're gonna go back to our project for step four where we move this product. We we move this query over into our component. So as I mentioned earlier the Shopify provider gives us access to hooks within our app and one of the hooks that we're going to use is the use shop query hook and that allows us to make those storefront API queries. We're also going to import the gql graphql tag library to give us syntax highlighting for our queries. That's not going to work inside of Stack Blitz, but it is a nice best practice for when you are working in a in a code tool that does provide that highlighting for you. So I'm going to copy this to my clipboard or we just import those two tools from hydrogen. And then over in my handle.server.jsx component. I am going to import those two tools. And then I can start building my query. So I already have the handle and so I need that handle before I make my query so underneath I'm going to start building my query. So I know the query is going to return an object and I'll come back to that in just a moment, but I'll start typing in use shop query. And then I'll open up my parentheses and that will give me the function signature. And I see all of the type hints that are helpful to make to help me build my query so you shop query expects an object and it expects certain parameters. So what we're going to focus on today is the query parameter and the variables parameter, but there are lots of other things that you can do with you shop query to optimize your API calls such as caching and preloading. So I'm going to open up that object. I'm going to get rid of this and I'm going to start typing query. And so that will be the first thing that I do so I'm going to eventually make a constant of query and I'll build that in just a moment. But the last the second thing I want to pass in is variables. And for variables I want it to match whatever I set up down here. So we're gonna make this a plain JavaScript object with a handle key and then the value of our handle as the value. And so we can do that in JS with the shorthand syntax by just passing and handle. So that's functionally identical to handle call and handle and so we can just use the shorthand here. So you shot query is going to return a object for us and we just want to pull out the data from that query for now. So I'll console.log that. Just to make sure that I did this correctly. Then the last thing I need to make sure I do is Define that query constant. And I'm going to move this to the bottom of my page and that's because these queries can get really long and so it's just a a nice way to make it so you don't have to scroll past that really long query whenever you want to work on your jsx. So I'm going to create a gql string with backtracks. head on over to graphical use this button to copy the query to my clipboard. And paste it in here. So that should be all I need to do to move this graphql query over to my server component. So let me open up my preview again, and I should now see in my terminal that I am returning an object with product Colonel and that's because I don't have a product with example as the handle in my storefront. So let's update that handle to be snowboard. So when I do that, I should see that I'm rendering the page for snowboard and my terminal now shows me a data object with product data and I can see the ID handle title and description so that works for now. So I've proved that this works and I'm now going to copy out my console log statement, but feel free to leave that uncommented if you want to reference the shape of the data. So I'm going to head back over to the workshop and if you got stuck at any point or your query isn't working correctly. You can copy everything from this block. Into your handle dot server.jsx component and that should get you back on track. So I'll pause just for a moment to let everyone catch up. All right. I see some questions in the chat and I see people are answering them. We are going to have time at the end for more generic questions. If you want to ask questions that are not specifically related to this Workshop. We'll have plenty of time for that at the end. Okay, so let's move on and talk about our first client component. So our server component that we worked on so far is going to be handled and rendered at the server, but we'll eventually need to provide a way for a user to make a selection of their product options and that's going to be managed with user State and we want to have a client component to handle that for us. So let's create a client component now. So in my stack let's editor in the file browser. I'm going to open the components folder and just create a new file. called products details dot clients Dot jsx And again, this is just going to be a react component. So export default functions. product details and I know I'm eventually going to pass in a prop of that product object. So let's go ahead and add it now. And then I'm going to return some jsx. So I'm going to cheat a bit and I'm gonna cut this out from our server component. Move it over to our client component. Rename this just so we know that it works and then we don't have access to that handle property anymore. But the product object that we're returning does have the handle so we can just change this to product handle. I'll save that and then over in my server component. I'm going to import my client component. This will be product details from our components folder. Dot client and the dot client is important. And then I'm going to render that components and make sure I pass in my prompt which is going to be data dot product. all right, and over my preview panel, I should now see Hello product details with my snowboard as a product property. So we've now refactored the message just a little bit. So the details on our page are going to come from our client component. So that's all we need to do to set ourselves up for eventually having that interactive piece on our product display page. So that was a quick step and now I can move us over to Step six. So now we're going to get into some of the fun bits of hydrogen and some of the really nice ways that hydrogen has been set up to make building e-commerce features really fast and seamless. So we've already talked about the Shopify provider component, but there are several other providers that are included with framework and we're going to be using the product options provider. And so what that does is it gives us access to a data model of product options data, which will help us to manage the rendering and selection of a specific product variant that will be within that options model. So let's start by importing the product options provider to our client component. So I'll copy this little line to my clipboard head over to product details.jsx. Make some room at the top. import it and then I'm going to wrap everything in my app around or everything in my component around that product options provider. And so I'm going to hit save here and this will format, but I'm also going to get an error in my preview. And I'll talk about that in just a moment. So it's giving us an error that it can't read properties of of null and it's looking for a variance object. So we'll eventually need to pass in a data object to our product options provider, but we actually not querying the right amount of data for our product right now. So if I go back over to our graphical interface, I'll see that I'm only querying for some basic product data, and I'm not querying for the variant data that I'll need for that product options model. So I could spend a while building that query for you, but we're gonna fast forward ahead just a little bit because this isn't entirely focused on graphql. So I'm going to copy this to my clipboard. Head back over to my handle server component. I'm going to replace the basic query with a more robust query. And then I'm also going to do that over in graphical just so we can see the shape of the data. So we have the same data that we are asking for before only now we're getting the description HTML. We're also getting some media data. So specifically some images for our product. So that's great. I'm going to collapse that and then we also see that we have variance data. So each one of those variant nodes represents a shopable and orderable products variant. And so we'll need these IDs in order to make sure that we can buy the correct product. And so this object is going to get consumed by our provider and it's going to give us a nicely built and accessible product options model where we can render and update the options data to make sure that we get the correct variant ID based on our selected options. So our query is updated in our server component. I'm going to save that. And then in my product details client component. I just need to update the provider to make sure that I pass in the product data. So I can just pass in the product object directly and it will know how to consume it. So that gets rid of our error and we now have a product option model that we can access and we can build details for so we're we're setting ourselves up for Success where we're not actually building the options details yet. We'll do that as our last step, but for right now, we have all of our stuff set up so that we can render some more details to our product display page. So let's do that in the next two steps. So another really nice feature of hydrogen is it comes with a lot of utility components to make rendering particularly data from our storefront API really nice and easy and one good one is the media file component. So not only does the media file handle the rendering of images, but it can also do videos and 3D models. So, let's see how we can use that. So I'm going to make sure I import the media file component. from hydrogen in my product details client component and then I'm also going to destructure a couple of pieces of data from our product objects. And that's just that's just going to make some copy paste work and a little bit a little bit easy here and cleaner. So then down below our message. Let's just render our media file components and make sure that we pass in our data object and that data object is going to be the media object and we just need to pass it in one of the nodes. So be media dot nodes and we'll just pass in the first node. So I'll hit save. and then over in my preview panel, I can see the hydrogen snowboard and I could play around with this to see you know, which images are available to me. And on a fully featured product display page you'd probably Loop through this and render more than one image, but this will just be a demo. So we'll just render the first image. So I'm going to show you one really nice feature of the media file component by opening up a full page. and inspecting the the product image So I see that my image components is not only rendering the image and the URL but it's also automatically making this lazy loaded and it's providing a source and then several Source sets as URLs. So the browser will know which product to or which image to load based on the browser width. So we kind of get all of that built for us because the Shopify CDN can automatically resize our images for us. So really nice developer experience because we didn't have to do all this work manually and it's really nice Shopper experience because they will get an optimized image and that is going to ensure that the site they're using is fast and perform it. So really great experience for everyone out of the box tip my hat to the hydrogen team for making that so easy for us. So that's one of one example of a really good component that we can use we're going to talk about the other pieces that we can use after we add in some styling to our product display page. So our our project came built with Tailwind already configured for us and so we'll be using that for this project and Tailwind is not required. It's not tied to hydrogen but we're using it in this project just to make the building and rendering of some of our components a little easier to where I don't really have to write CSS for this demonstration. So rather than typing out a lot of these utility classes. I'm actually just going to copy and paste. And I'll talk about the structure of this display page. So if I copy that section to my clipboard. And then give and then get rid of everything inside my product options provider. I'll paste this in and just quickly reviewing this my sections going to create a grid for me and then that grid will have two columns. The left column is going to be a media file component which we just showed and the right column is just is going to show the title of the product the vendor of the product and then we're going to render that description HTML as actual HTML using this function. So I'll save that. Open my preview again, and I can now see that I have a really nice rendering of my image and some product details. In the full page preview I can see that this is a nice two column layout. So we're well on our way to building a really nice looking product display page. So this wasn't really hydrogen specific. So we just gonna kind of blow through a couple of the tailwind and markup specific pieces of this demo. But we're going to add a bit of interactivity in the next step and to do that. We're going to build a new product form component and we'll just add that to the bottom of our product details file. But we're going to use a new hook. And so that is the use product options hook and we'll be able to use that because we've set up our product details form component with that product options provider. And so if you look at our demo code here, we're going to pull out the selected variant from that use product options hook because we'll need that variant ID so that we can pass it over to our buy now button to make sure that we buy the correct product. So I'll copy this line to my clipboard. Actually. I'm going to copy this whole function to my clipboard just to save a bit of typing. Down at the bottom of my product details. File I can paste this in. I need to make sure that I import use product options from hydrogen. If you accidentally save your file here, it may try and pull this from a different source, and that might break your app. So just make sure that you're pulling it from at Shopify / hydrogen. And then let's just print out the selected variant. So I'll just make this selected variant ID. And then I just need to make sure I render this product form, which I will do by including it just under my description HTML. And we don't need to pass it any props because we're using hooks instead. So since this is a descendant of the options provider we can use that use product options hook. So if I save that and then show the preview on my page down at the bottom, I now see the product variant ID and so that'll be what we pass into our buy now button. So let's add that by now button now. So back up in my import statement. I'm going to import the buy now button, which is built for us in hydrogen. And I'm also going to import the money object which gives us a really nice way of rendering a price object into a shopper-friendly currency strength. So I'll show you how to do that as well. And again, this is going to get a little tailwindy. So I'm going to do some copy pasting. But it's relatively straightforward. So inside the form we're going to render our by now button and the variant ID prop. We've already figured out can come from selected variant.id and then inside that button we're going to render a span that basically creates a black background with a white text button. We're going to render a Buy It Now string and then the price of our currently selected variant by passing in the price V2 object into a money component. So really nice component features that make building out some of these features really fast. So if I paste that in and let Auto formatting take care of this for me. I should now see that at the bottom of my preview that I have a Buy It Now button and it is 600 Canadian dollars for this selected variant. If I click on this button inside of Stack Blitz, it's probably going to give us an error. So instead I'm going to do that over in my full preview. And this is linking out to a demo storefront which is password protected. So there's a chance that this will actually get blocked and ask us for a password. But it looks like it's going to actually route us to check out. And we'll see that our product is added to our cart and we're ready to make our purchase. So what I mentioned a moment ago isn't going to be an issue for a production store. But when we do our development on demo stores with a password protection thing, sometimes the handoff from the app to check out will require us to enter in a password. So we've added some interactivity to our page and we're able to buy a product. The problem right now is that we can only buy whatever selected variant is available for us when the page loads so our last bit of interactivity is going to be adding a option selector. So let's do that in the next step. So again, we're going to skip forward a little bit and just show you a product options component that we've already built, but it uses these same principles of our product form where we're using that use product options hook. So let's take a look at how that was built. So the product options is a separate component and we'll see that the use product options Hook is being used and we're pulling out all of this data. So we have an options array. We have our selected options and we have a function called set selected option where we can update our data model with a newly selected variant option. So when we return our jsx, we're going to iterate over each of the options and then we'll pull out the name and the values. So if the values length is equal to 1 that means that we can't make a selection. So we'll just skip over it and not render it. Otherwise, we're going to render a flex grid and for that grid, it will have a legend where we render out the name of the option and then we're going to iterate over the values of that option. And for each value, we're going to render a radio input and so a radio input is a nice native way of ensuring that we only ever have one option selected at a time. And so the radio input also provides us with an on-change callback function. Inside of that callback function we can run the set selected option function which again we grabbed from our used product options hook. So that is going to update our data model and we pass in the name and then the value of this specific option. And the last bit of markup tailwindy goodness is that we're going to render a box for each one of our radio inputs. And if that input is checked, then we'll have a border gray that renders underneath it. So A little bit of iteration and looping. So this is more react code than it is hydrogen code, but I did want to highlight the hydrogen pieces, which is the hooks and how we update our model right down here. So let's head over to product details and import this product options component. So import product options from and we're already in this folder. So let's just make sure it's product options stop client. I can spell Okay, so product options is what we're going to render and we'll render it inside of our form just above the buy now button. And again, we don't need to pass props to this component because we're using hooks. So this is going to be a descendant of the product options provider so we can use those hooks. So down over in our preview. I now see that I have an options selector where I have size binding Mount and material. And just to prove that the data model will update for me. If I make a selection. I can see the price for my variant right now is 600 Canadian dollars if I select a different size. I'll see that my price updates so behind the scene. What's that doing? The set selected option function is running that updates the data model and then that will and then react will be queued to re-render The Descendant components that need to be re-rendered. So all that is taken care of for us in a declarative way using the providers and hooks programming pattern. So really nice way to render out our options for us and the hydrogen Hooks and provider components made that really fast. So I can once again try and test this out by selecting a different product purchase. And I'll see if I can purchase this product. And so I did get the the clothes store bug so that won't be a thing with the production store. But you know, we're coding on a demo store. So that's it for the first piece of this Workshop. We built a functional product display page and there's a lot more that we could do with this and a lot more that we should do with this if we wanted to make it production ready. And so you have quite a few options of where you can take this for a Next Step. So we have a lot more that you can explore with our docs or you could try extending this Workshop by improving upon it and fixing bugs and adding new features like disabling the buy now button if a variant is unavailable. You could also try displaying a message on that route component if a product isn't found. We also have a really nice SEO component that will handle the rendering of stuff like title and meta tags. So that's really nice to explore and then you could also try building out a fully featured cart, but we're going to do that in the next section and we're going to jump to that right now. So you have the option of building out a full fully-fledged cart with our build a hydrogen storefront tutorial on shopify.dev, but we're just going to do a really quick version so that it fits in within our time block here. So I'll close out of the first workshop and then jump over to the second Workshop where we add a cart page to our hydrogen project. And so if at any time you want to jump into just this project you could Fork the completed project that we have here in a link. But since I've already built out our project and stack Blitz. I'm just going to continue with my existing project. So much like we did with our previous project. We're going to start by setting up our route component. So I'm going to make sure that I kind of build this in a way that's similar to our product display page where we have a server route component. And then the majority of our details that are rendered to the page are going to be handled inside of our client on it. So I'm going to create a new cart details client component. Just paste that in and again, it's just a simple message and then I'm going to also set up a server component and it's going to go in the slash cart route. So in our routes folder I can add a new file and that will be cart Dot server.js. Paste in this data. And again, we're just rendering the layout and the cart details. And then I can go up to my preview and go to the cart route just to make sure I did that properly. So that works for us great. And I am going to be going through this at a really fast clip because we are limited on time. So I apologize if this is a little too fast for you, but you should be able to follow along if you do this in your own time. So because we need access to cart data, we're also eventually going to need to set up a provider and so we're going to do that in this step. So in addition to Shopify provider and the product options provider we can make use of another provider that's built for us and we have a cart provider. So I'm going to add this to our app.server.jsx component. First I need to make sure I import it. And then in the Shopify provider component as a direct style. I'm going to render the cart provider component. And that means that my entire app will have access to cart data. So I'll hit save here and this is actually going to cause an error but this is really just a framework here where all I need to do is stop and restart my server. And that will get us back to a running cart. So we will now have access to the hooks like the used cart hook in order to access data anywhere within our site. So the first thing I want to do is update my header so that I have a mini cart bag icon and I can click on that to navigate to my route my my cart route page. So we're gonna introduce both the used car Hook and the link component. so what we're going to set up is a link component. That's just going to work with our router to direct us to the cart page. And then inside that link component. We'll just render an SVG bag. And then as a little bonus if we can pull out the total quantity from the used cart hook we can render a little notification dot with our total quantity just rendered as a little bubble. So I'm going to copy all this to my clipboard and create a new component called cartling Dot client.jsx. I'll paste that in and then I'm going to bring it into my layout component. And then let's render this directly underneath our hydrogen Workshop text. Okay. Sorry. My zoom is in the way so I should now see that. I have a bag icon down here. These don't look quite right right now. So let's make sure that those are vertically centered and I can do that by updating my header classes so that this is now a flex container and then we can make this vertically centered with items Center as a class and that should now make it is that right? It's item Center by 10 Center is what I wanted and so now both of these visual elements are vertically centered inside of my header block. so I can now click on this bag icon and well, let's make sure that let's go to the products. Snowboard products and so I could click on this bag link now and I head over to the cart Details page. Okay, so that link is working for us. All right. Now we're going to update the product page because so far we're able to render a cart page and to go to our cart with a link, but we're not able to add a product to our bag. So we need to be able to do that. So we've already set up the buy now button and we also have an add to cart button that works much the same way. So you pass in a variant ID and it will take care of adding that product to the cart for you. So let's make sure I import my add to cart button. And I'm going to do that inside of my product details client component. And then again, this is going to be a little tailwindy. So what I'm going to do is replace the buy now button and this will be exactly what we did in the this is exactly the button we built in the previous section. The only difference is we're wrapping it in a flex container and then we're adding in the add the cart button below it. So these two buttons will Flex against each other. So back down in my product form. I'm going to replace the buy now button. I have here with the flex container that includes the buy now button and the add to cart button. So let's go back to our product snowboard. mmm That's wrong. There we go back to our product page. I now see that I have a Buy It Now button and an add to cart button. So if I click on add to cart button that should take care of adding a product for us and now I see up in my header. I have a little bubble notification with A1. So just to give you a really quick peek under the hood. Let's take a look at what is happening on this page? So I'm actually going to go to a different product just to make this look a bit different on our cart page. We'll go to the hosted snowboard. And I'm going to open up my Dev tools inspector and navigate to the network tab. Clear out my existing. Requests and then I'm going to click add to cart. So what that will show is a graphql.json request and if I inspect that a little bit more I can see that that was initiated by the cart provider. So it's making the API call for me. And if I look at the payload I can see that what it's passing is a query that is a mutation which is a fancy way in graphql of saying edit or update data and we're going to pass in some data to a cart line ad mutation and that variable data is all of this information here, but the add to cart button and the cart provider are taking care of formatting all this data for us. So all we really needed to worry about is that merchandise ID, which we passed in is a variant ID to our component. So all of that is kind of handled for us and abstracted away. And what we get back from that graphql mutation is we get new cart data and so the cart provider will be updated with this new cart data which includes information like the Total Line quality, which is what is updated here in our little bag icon. So all of that has been abstracted away from you. So you can just use the providers and hooks and built-in components to make those API calls for you really nice and seamless. So again, thanks hydrogen team you've designed this so we can build things and really fast and intuitive way. So once we're actually able to add some products to our cart. Let's go ahead and render some cart details. So again, this is going to be a little heavy in the jsx. So I'm going to do some copy paste work, but we'll talk about what we're using from the hydrogen framework. So again, we're using that used cart hook. We're also introducing a new provider. So the cart line provider is going to be a provider specific to that cart line item and that will give us access to data from that specific cart line. We're pulling in the image and the link which is which are components. We've already covered and then the use cart line Hook is going to be available to us once we use the cart line provider. So we're going to export a default function where if there are no current line items. We just render a no items in cart message. Otherwise, we're going to iterate over the line items and that's going to return jsx where we set up a cart line provider. Where we pass in that line object? And then for right now, we're just going to render the Json of that line. And then down below I've set up to utility components for us to help us out when we actually expand the functionality of our cart Details page. So I'm going to copy all this to my clipboard. Head on over to cart details and replace what I have so far. I head over to my cart page. I should now see that I can see Json for each one of my cart line items and this is all the data that I'll need in order to render a cart page. So super helpful. Let's go ahead and get rid of our our pre-block where we're Json stringifying our line data and instead we're going to render some markup for each one of our line items. So let's go ahead and first pull out some data from that use cart line hook. and we are we already have a a component that was built for us actually gonna delete that uncomment this and so for each line item, we're going to return a bit of jsx. So let's first pull out some data from each one of those cart lines. And then let's render some data. So we've already used a couple of these components before but they should be familiar to you. Now. We have a link component which is going to direct us to our product display page for that product by handle. or render an image of this product line item and then we're also going to render the merchandise title, which is also in a link component. And then rather than rendering the merchandise product title below it will render the merchandise title, which is a differentiator to help us understand what selected variance we have for this product that are configured on our product line item. And then lastly we'll render the current the quantity for each one of our line items. So I'll go in and I'll paste in my return jsx with our additional data. So we should now see in the preview panel that we're rendering a product image the title The variant data, which is that merchandise title and the quantity. So we're now able to see the cart data on our cart page. And the last thing we need to do is add two pieces of interactivity to it. So we'll add a remove button for each one of the line items and then we'll add a button so we can go from the cart page to the Shopify checkout. So let's do that in our next two steps. So we're going to add a remove button and that remove functionality is going to come from the cart provider. So the cart provider gives us access to a lines remove function and that lines remove function gives us the ability to remove one or more line item by ID. So let's first grab this from our used cart hook. I need to make sure that that is imported and it is great. Or our cart line items we're gonna grab the lines remove function. And then we're going to add a button below our quantity field. So that when we click on that button, we run the lines remove function and then pass in that line ID. So again, there's a little tailwindy goodness here where I set up a couple of classes. That make this a white button with black border and black text. And then in our onclick Handler save this onclick Handler, we run the lines remove function and again, we can remove more than one line item. So this is actually going to be an array of line item IDs. So this is usually a common typo here where you think you just pass in one line ID, but it's an array of line IDs and now we're set up to actually remove products from our cart. So if I click on this remove button that should remove it from our cart and we'll see that our total quantity updates and we only have one other product in our cart. So that's a great way to add that remove functionality. So again under the hood if I run this lines remove command, it's running a mutation on our cart that will remove that specific line item for us and then return a new cart state with all of the data. We need to render that data on our page. So again a nice and simple way for us to declaratively State what the state of our app should be using providers and hooks. So the last thing we'll do and this will be the end of our Workshop is we're going to add in a checkout button. And we are just going to render a simple link component, but we need to get a checkout URL that is specific to our cart. And so this is going to vary for each person. So your URL for your cart is gonna be different from my URL for a cart, but we're able to access access that within the framework very easily by pulling it from the used cart hook so inside of my checkout actions component, which is just kind of a placeholder component I have right here. I am going to use the used cart hook to pull out the checkout URL and then inside of the return jsx will render a link that's going to point to that checkout URL. So again more tailwindy goodness where we set up a black button. with white text it's got two return tape two return statements don't want that. And so this link is just going to point to our checkout URL. So now I see that I have a continued to check out button. And again, I don't think this is going to work from within stack blitz, so I will head over to my cart page. and if I click continue to check out That will take me over to my checkout page just like it did with our buy now button. Our products are added to our cart for us and I'm ready to move along with my checkout flow. So that's it in the span of a little over an hour. We have built a pretty feature-rich product display page and a functional cart page. So I'll leave you with a couple of bits as a conclusion. First one is I mentioned at the end of the last Workshop is we've dug into quite a few bits and functions and patterns of hydrogen, but we haven't shown all of it. So there's a lot more that you can explore and build with hydrogen and in order to do that. You just have to dive into the docs to learn more. You could try extending this Workshop to add in a quantity selector for each line item. You could try adding a shop pay button to your checkout actions component. Or if you want an extra super challenge, you could try rendering all of the cart details in a slide-out mini cart component and we do have a full tutorial that covers that on shopify.dev. As a last bit of communication, I'll leave you with a link to our Discord server where you can join at that link and we have a hydrogen Channel where you can talk with other people that are using and building with hydrogen. So with that I want to thank you for following me along in this workshop and we're gonna open the floor up for questions. And these can be questions that are about the framework or about Shopify and we have people on our hydrogen product team. So I'm just developer Advocate. I'm here to facilitate communication between the developers that build with hydrogen and the product team that hydrogen the product team that actually builds hydrogen. So with me today, we have Matt we have Daniel and we have Brett who are the engineers that actually built hydrogen for you. So I'm gonna shut up now. I'm gonna let my voice rest and I'm going to turn it over to the hydrogen team to handle the Q. Section so take it away guys. Hey, everyone. Brad actually had to step out. So it's just me and Daniel here today. I'm seeing no QA answers or QA open questions. So we'll just give folks some time to fill those in or if yeah, if anyone has any questions. I also just wanted to plug the Discord as well as a place to. you know if you think of questions after this Workshop, or maybe you fell behind and you're still working on your on your storefront and the teams always monitoring that and it's a good place to kind of feel your questions later on if they if they come back at you later. Yeah, and it's also a great place to check in for news because hydrogens always got new things that are being published so bug fixes new features as the framework evolves, you'll be able to talk with other devs and see those news updates inside a Discord. So it's really nice community space to make sure that you know, you're up to date on everything hydrogen and you can talk about how everyone is building with hydrogen. So maybe a shy crowd today if we don't have all that many questions. So if you'd like you can you take a few moments while either of you have the audience and you know, just talk about some of the features of hydrogen you really like or you know, what what you like about hydrogen's current state and its future. Yeah, I can I can talk about it the for example the demo store that you can actually check it out that hydrogen Dodge shop. I don't know how to write it here. I'll see if I can pull it up. Yeah. Like here we go. Yeah like this this demo we were able to build it in around two three weeks with I love components that we had already done and it has a lot of things. I mean, we had all the products. We have a car that opens and closest and The variants and and I think what I love people are doing is just going there and copying some of the components that we build there. But yeah like hydrogen. So what we are doing now is like we're like also trying to separate these components so that they could be reusable and not necessarily with hydrogen, but it's a but it's a cool thing that we also recently saw some other store. Uh, what's the name atom? Did you see that one day a bit? Maybe we can open that one? Yeah, it was Adams that I always atoms that I own or that calm adams.com. I'll post in the chat. Yeah, and now what was impressive this was done what by one developer in around three months and and I think that like the average time for building. Headless storefronts. It's around 12 to 18 months. So it's very fast for somebody to build something like this and as you can see I think I think the main difference is like how custom you can make this compared to yeah, like a liquid. Like a liquid starfront will allow you to okay, we have this things though. It will be easy. There's no developing maintenance, which is great. Like I've given to some friends that and they have never touched it. I've never had to touch it and they just do their thing and sometimes they ask me if I show is that an app or not. If I were going to do this, I would have to probably touch it if they have any questions, but you know Um and our example, but butcher box. Well, we can show budget box really quick as well. I don't know is there but yeah. Yeah. So what's interesting about butcher boxes that they have very specific cards where they depending on what you choose you can like build the box with different set of things of meat. And so I think this is the sort of situations where maybe yeah, like a custom solution will make sense. Yeah, I don't know. This is just my experiences. Yeah. Yeah, it does kind of unlock a lot of different possibilities. Sorry, go ahead Matt. I was gonna say it's exciting for us to see these things come out as we work on it in like for example, the adams.com one like we didn't have any involvement in that it just Came across our radar and it's called the I mean, it's a really slick looking site, which is nice, but it's just cool to see people use their stuff and build things easily and quickly and without any balance really because it's just just react and apis and have this Commerce is pretty powerful. So Yeah, I think it's great that if you think about Shopify Development A lot of it is it feels really custom like there's a lot of internal knowledge. You need to figure out with working with liquid or working with apps. And so You know, we kind of have a different Paradigm with hydrogen where it's like if you know react and you understand a little bit about graphql apis. Yeah, you're everything's unlocked for you. It's all there and so typescript helps us with you know type hinting and making sure that we have the right parameters and inputs and properties and you know use the tooling that exists in the community and you can build an iterate really quickly. Yeah, I guess in terms of some other features that we provide and that we want to continue to build up as we do have a CLI. Oh can help you spin up an app really quickly choose between a few like she's between the demo star template and and also a Bare Bones. Like the most minimal version of the hydrogen website that you can provide so we have those two options as templates. And then we also have support for both JavaScript and typescript and the CLI can also help with building and deployment and other things just like common sail eyes with other Frameworks. So this is something that we're building up a lot recently as like a lot of the CLI work at Shopify has been ramping up and we've been a part of that so That's just a shout out to some of the other tooling that are you will have available to you. If you choose a hydrogen route that wasn't so much demo in in this Workshop because of the nature of using staff books, which is great. So if you do want to pull down something and start hacking and your own vs code or whatever then there's the CLI in the docs for that. Yeah, great. I think shopify.new also get you a quick way of I'm sorry hydrogen do if I can type it. Will also kind of get you to a nice starting point where you have a template already set up and you can just start building site really quickly. So yeah a lot of different options to get you up to speed and and playing with hydrogen as a framework in a short amount of time. So great job on making everything, you know, super easy and available for everyone. Yeah, this is this I will start usually if I want to play with something and try something and go to you know, the API of Shopify and see if I can. Fetch something and try to this is the the quick way without having to download the repo. So yeah, I recommend that one. Yeah, it's it's a great time to be a developer. Like I just I just type something into URL bar and I have an ID and a side already built for me so I can start hacking away. And we also support we have we have specific links in our in the repo for each of our templates. It was I mentioned earlier that will actually produce a stocklets for that specific template. So We want to even start with a something. That's not typescript or typescript. Or the more minimal template I mentioned earlier you can actually do that as well, which is pretty cool. Yeah, these these editors like chocolates are just doing insane things like it's so it's so cool to watch and and just like how it lowers the buried entry for our for kind of getting things up and running. Even just with helping us and support like it's so nice when people just post the stacklets. you're all to their bug or to their issue that they're facing that they need help and we can easily just see it like it's so nice to have that available to us. So really really excited about that. Like I think in the next like I mean, we're seeing it right now. It seems like every day things are releasing when it comes to like stocklets code sandbox get good like things but like I think the next couple years you're gonna be really exciting not in that world. Yeah for sure. We do have about five minutes left. I don't know if there's anything you wanted to shout out in the hydrogen Community or in the react community at large. Yeah, we have a captive audience. So feel free to speak your mind. I don't really have anything Daniel does have a workshop or a lightning talk. What is it on Friday, Daniel? Maybe you want to plug that some people can catch it. Yeah, right. I have a reacted bands London this Friday. I have a talk about server components and I explained a little bit about them more. Um, yeah, whether the advantages disadvantages and our experiences because I guess they are not like officially out and like some of the meta Frameworks are still kind of releasing them. So there's some discoveries, of course from our sites since we've been since we launch hydrogen in June and so I just kind of do a lighting talk around them. Yeah. I don't know. What's the first address Man, I really don't know how to use this interface. So let me get it for you, but I'll send it a second. Great. Thanks, Daniel. I have a question for all of you since you're here much Daniel and David there's wind up. Well, what's your favorite or what, you know newsletter or react blog is your go-to at the moment? So I I'm like that active on Twitter like many times and probably less than many most even on the team and things like that. So I actually am very into consuming. They kind of keeping up to date with the community news via newsletters and podcasts. I really like a lot of the podcasts have been coming out lately that are just like really specific to like Dino, which is just the project. I've been following along with a lot. Um, so I think there's one it's just like, you know news or there's only like like Arduino weekly or something at that that other follow along more recently but a lot of the classics like syntax.fm shot talk show JavaScript Java and front and happy hour. I use those probably for a lot to keep up and in terms of newsletters. I just really like the standard ones like like yes, yes next one and the react weekly one like all like the weeklies like yes next week and react weekly, I don't read everything. Obviously. I I scroll past a lot and kind of just whatever headlines kind of if there's something interesting that's always talking about but and then the other one that I kind of like lately, it's like you I got Dev I think it is that's like kind of funny. Um, I think that's what it is and they have a newsletter. That's kind of I was gonna say now I was gonna yeah, that was my favorite is hilarious the guy I don't know right but he writes so many jokes. It's really great. It's like a bites your weekly those of JS is called. Yeah. That's the one. Yeah that what I really thought this it stands out and I tend to like we read it all a bit more reliably than some of the other ones which are just like lists that you know more distracting. gray comedian Recommended. Oh, I'm gonna have to subscribe because this isn't on that I subscribed to so, that's great. The other one that I provide that wasn't mentioned as I follow Kent Dodds on Twitter and he's got a lot of great content some of it specific to react. So it's specific to remix and then he's got another Channel that's just web specific and I think he started a newsletter recently and Kent does a really great job at teaching and instructing and he's got high quality content with great diagrams and Pretty much everything he puts out a solid gold. So I love to learn from him. Lovely. All right, cool. So I think that Wraps it up really? Well David. Good job. Thank you so much for running it Daniel much for your insights and for answering questions and to everyone who's hung out with us still right now. We appreciate you. Thank you very much. If you will be in person at react Advanced Land and this Friday, you know, like Daniel has mentioned he's going to be there. So go say hi, but also go and see if lightning talk. It will be at 3:30 p.m. Local time, but we truly appreciate you. So thank you for joining and enjoy your day. Take care. Thanks. Mercy. Bye.