Transcripts
1. Introduction: Hi, my name is Gavin. I'm the founder at Disco, a company that helps Shopify store owners make the most of their stores through customer theme development and customer application development. I've also released a couple of products around Shopify development, including Mastering Shopify Themes and Mastering Shopify Apps. There are also a couple of open source projects that I worked on. All of these things sort of have the goal to help developers like yourself develop Shopify themes in a really efficient and easy map. Being involved in all of the different parts of Shopify, means that I have to constantly learn and relearn a lot of things around Shopify theme development, and that's really what I'm trying to share with you through this course, the best practices, the tips, tricks and techniques that I've developed over the years. The title of this course is Advanced Shopify Theme Development, and it follows on from Kurt Elster's introduction to Shopify Theme Development. That course is also available right here on Skillshare. This course is premised on you not only having existing web development skills, but also having a little bit of a working familiarity with Shopify. So, if that's not the case yet, I really suggest you go back and take Kurt's course before coming back to this one. Assuming you are comfortable with the basics of Shopify development, then this course is going to focus on leveling up your skills in two key areas. The first one is going to be on improving the process we use to develop themes. So, looking at the tools and techniques around that sort of thing. The second part, to make sure that we're not just talking about this stuff in a vacuum, is to dive into some real-world scenarios, and look at code and the development practices we'll actually use in a real scenario. Taking this course should give you the skills and confidence you need to tackle larger Shopify development projects and incoming client requests. This means you'll be out to deliver more value to your clients and to your company. In turn, that means you're able to charge more for the value that you're creating
2. Course Project Overview: As with a lot of things the best way to learn Shopify theme development in my opinion at least is through actually doing it, and that's why this course contains a class project. I really encourage you to take a crack at that once you've watched through the video the first time. The project will begin with you downloading the base theme. It's functional but it's really pretty simple. Then we just ask you to apply some of the techniques that you'll learn throughout this course through that theme. So, things like adding dynamic filtering and sorting, some Ajax functionality, add to Cart things like that. Then you also get the chance if you really wanted to to add your own little bits of styling with CSS and SASS. Working through that project should only take a few hours and we'll give you some exposure to what I think is some real worlds practical scenario for Shopify theme development. The only things you really need for the project are a development store and a text editor of your choice. You'll need to be familiar with how to set up a development store. If you're not familiar with that, then head back to Kurtz course on Introduction to Shopify themes to give yourself a refresher. If you get stuck at any stage with the project, then you could check out the GitHub repository which has examples for every step of the projects or you could always get in contact with me as the class later and I'll try and help you out. Once you've completed the project, it'd be really great if you could share it with myself and other students and you can do that via the Skillshare platform. All right. Let's get started.
3. A Better Development Workflow: The first topic we're going to cover is development workflow. So, the process we use to develop, test and deploy our themes. The reason that I think this is an important thing to tackle is because the more effort we spend on our workflow, the easier it is for us to develop these themes and the more time we can dedicate to building things that customers actually care about. The goal here is to deliver things faster and more professionally, we can avoid repeating ourselves in manual steps and it also makes it a little easier to collaborate with other developers when we're working together in a team. So, let's start at the start and look at what we get with Shopify's default online editor. So, we get to that from the Shopify Admin and once we open it up, we see that we actually get a pretty good overview of our theme structure on the left here and then when we actually open up files, we get nice features like liquid syntax highlighting and there is a limited version of revision control. In that we can make change and save and then wait to go back to older versions. But there's still some pretty severe limitations with this approach. So we're developing the cloud. So, if we have a preferred local editor, we don't really get the advantage of being able to use that. We don't really get a change history across all of the different files. In our theme, it's not very easy to revert changes in large groups and of course it's very difficult to collaborate with others using this workflow because we don't really know who's editing what files and whether we're going to overwrite changes. Given these problems, we're going to start looking at ways to fix them or to get around them and make that development process easy. The first thing we're going to do to help you out with that is by looking at the Theme Gem. Now, the Theme Gem is a small command line utility that automates the process of uploading and downloading files between your local development machine and a Shopify theme that you're working with. Let's see how to get set up with the Theme Gem. So, the first thing you want to do is make sure that you have Ruby installed, as it is a RubyGem. If you're not sure how to get Ruby running on your platform, then you can Google for instructions on how to get that set up. Then once you've done that, you just run a gem install command with the Shopify theme. Gem is the argument that'll install the Gem and we then have access to a theme command line option, which if we just type in our command line we'll say we get a bunch of usage instructions. Because the Shopify Theme Gem uses the Shopify API to upload and download assets for us, we're going to need to set it up with some API credentials in order to work with a current theme. So, that's what I'm going to do here. I'm creating a new private application from within the Shopify Admin. I'm just going to give it a name something like Theme Gem and then we can use the credentials generated here and pass that to the Theme Gem. So, you will see that once you've created an app, you will have this API key and an API password. So, to get set up with a new theme, what we're going to do is jump back to the command line, create a directory for our theme and then once we sudo into it, we can use the theme configure command to set up the configuration for us. So we're just going to use the information that we got in our admin pass out to configure. So, we pass in the API key, the password and then we're also going to pass in the domain of the store that we're working with. So, this is just the.myshopify.com account and then once we hit enter, that'll create a config.yaml file. Taking a look at the contents of that file, we can see that it's added the key and password that we pass into this configuration file and we don't really need to worry about the other configuration options for the moment. As you can see, I've now run a theme download command and that'll basically use the Shopify API to get a list of all the assets in our current theme on our Shopify store and download them locally. So, if we open up a text editor such as Sublime Text and look at this locally, we can see that we've copied all of the files from our theme down to our local machine. So, we can now make use of one of the best features of the Theme Gem which is theme watch command. So, if we run that inside a directory where we have a theme, we can then use a local editor to make changes to those files and have them automatically apply loaded to the Shopify store that we're working with. So, to see an example here, I'm just going to change the title of my page and then once I save these changes, will see that that automatically gets uploaded to the Shopify store. So, this is how we bring development local and avoid that problem we were talking about before with the default online editor, where we are unable to use our preferred editor or use local development methods. The second tool we're going to look at to help us with our theme development floor is Git and if you haven't used it Git before it's a revision control system that's used very commonly in a lot of software development including web development and it gives you a lot of advantages in that it makes it a lot easier to collaborate with other people, it gives you a way to keep a revision history so that you can see who made what changes when with your themes and it also plays very heavily into some of the advanced deployment strategies that we're going to be looking at in later lessons. Let's take a look at how we'd go about putting a theme that we have locally under Git revision control. So, the first thing to do is to check that we actually have the Git command line client and we do that just by typing git--version. If you're running a Mac or Linux system, then you'll have this by default, you may have to install this manually on Windows. Once you've done that, you can run the git init command in the local directory and that'll set up your Git repository. The first thing that I do when I create a new Git repository for a Shopify theme is to create what's called a gitignore file and add the config.yaml file to it. So this just tells Git that we don't want to track changes to the config.yaml file and that's because it contains API credentials for our store, so we don't really want to be committing them into a repository and potentially exposing them to the public. So, once I've set up that ignore file, I can add all of the files in my theme with the git add command and then commit them using the git commit command and we'll see that all of the files in the directory I've been committed to the Git repository. So, this git all going to be very familiar if you've used Git before. If you haven't used Git before then I really encourage you to head out and find one of the excellent tutorials available online on how to use it. It's a really useful tool we'll be using it a lot during this course To give you an idea of how the workflow operates with Git. So once we have set up our repository, as we've just done, and then I would make changes to our theme. So, for example, here I'm just changing the title of the page. We save those changes and then back from the command line, we can get an overview of what's changed using the Git status command and then we can run git add to add that change to our next commit. Then finally, we can run the git commit command to actually finalize that commit and there are GUI tools around that'll help you with this workflow if you prefer to use that rather than the command line. But once you've added all these changes, you'll see you're able to run git log and get a history of who made what changes and when to your theme. We've now seen two ways to improve our development workflow, we have brought our theme development local through the Theme Gem and we've also placed our themes under revision control using Git. We're going to look at some more development process techniques later on in the course when we look at advanced theme deployment and also workflow automation. But for now, I really want to get stuck into some more practical stuff. So, some actual code, what we might see in a real-world Shopify theme development scenario. But as we start tackling that you can use the things that we've just learned in this course to follow along.
4. Product Customisations: Time to dive into some real theme editing, and we're going to start off by looking at product customization. So, how we can let visitors customize their products from the product page. This is pretty common functionality. You've probably seen it on a lot of themes in the Shopify Theme Store, on Mosaic on their sites around the web. But the approach we're going to take is to start by looking at the very basics and see how the functionality on a Shopify store gets built up from these basic components. In doing that, we're going to be focusing on the three most important things when you're building a product page. The first of these is to make sure that you're communicating to the customer, so telling them what options are available, what they can do to configure their product to make different selections. The second thing is to make sure that it's easy for them to make their selections, so depending on what type of choices they need to make, you're able to provide the appropriate input and controls for them to do that. Then the final thing is to provide feedback, so that if they do make a selection, so they change the color of a product or something like that, that change is reflected on the page, so that I can see that that has been received and see what effect it has on their purchase. Let's start by introducing the Candle store which is the demo shop that we'll be using throughout this course to work on. So, this is the product page that we're interested in. We have a set of variants. The variant options that we can choose between for this particular products of the candle is the color of the candle, and whether the candle comes with a lid or not. We're also able to add a custom property, custom line item property to the candle which is an engraved message, and then finally we have these additional little bits of metadata which are the displayed price and the displayed image. The price and the image depend on what particular variant we pick. Before we start looking at how to improve this product page, let's take a look at what we've got at the moment. So, we've got a standard product page with a select drop down with all of the possible variant options. Under prices we're able to enter a custom property to a message, and then when we add to cart, we get taken to the cart page as per usual, and this is all operating without JavaScript. So, to take a look at the actual HTML behind this product page at the moment, we will say it's written pretty straightforward. We have a title of the product. We have a section that contains all of the product images that we saw on the left hand side there where using a little bit of liquid logic to work out what the featured image should be based on the first or selected variant. We then have a section that's the product form, which contains the actual HTML form that we saw, the product's price. It also includes that select with the different variants and prices in it. We have a section that contains the custom properties for the products or where we were adding that engraved message and then at the very bottom of the form, we have the add to cart button. So, all in all a pretty standard approach to a product page. So, thinking about ways that we can improve this product page, one of the first things that jumps out about his page to me is the select box, having all of the options in the one drop down doesn't really show the user what the different options are and what they can select. So, we'll look at how we can change that. So, jumping into the theme.liquid, we're going to add a bit of JavaScript and we'll come back and step through exactly what this is doing in a second. But if I make this change, save the file, and we're just going to check that theme, watch is running and uploading our changes automatically to the theme store. If we refresh, then we'll see that we've actually split those options out, so it looks clearer to the user what the choices are. Coming back to the JavaScript that you wrote, just stepping through that, we can say line 20 we're checking to make sure that we're only including this on product pages, line 21 we are including the option selection JavaScript which is a Shopify provided library which does actually most of this magic for us, and then the rest of this JavaScript is setting that up basically. So, it's calling that new Shopify.OptionSelectors and it's passing the ID of that original select box. So, it's saying, target this select box and this is what I want to split out into those separate select boxes, and then we pass a few options to that initializer. That basically does everything that we just saw. So, this is good, but if we jump back to our page, you'll see that we don't actually get much feedback when we change these options. So, in the URL bar at the top, we can see that the URL is changing but we're not actually seeing that change reflected on the page. So, the image isn't changing, the price isn't changing as we change these options. So, let's see how we can resolve that. So, the key to this is going to be the onVariantSelected callback function which we flashed out as being just an empty function earlier. So, this is a function that gets called anytime the options on your page change and a new variant is selected, and it's passed the variant as adjacent object and also the selected that actually triggered that change, so this select box. So, what we're going to do here is just update this function to change the dome of our page, to update it based on the variant that was selected. So, you can see here the code I've added we're updating the price that is displayed and we're using the variant price and Shopify's format money function to do that, then we just find the price element and update it as needed. We're also enabling or disabling the add to cart button. So, sometimes we might be selecting a variant that isn't actually available and we need to disable the button. Then finally, we're updating the featured image on the page, so we're checking to see if the variant has a featured image linked to it, and then using the Shopify getSizedImageUrl method to get the proper URL for that particular featured image, then just finding the featured image dome element on the page and changing its source. So, saving that and checking that's upload to Shopify. If I refresh the page now, we should see that the page is getting updated as we change these options. So, we're saying the featured image is changing, the price is changing to reflect the variant that we've actually just selected. So, that's a nice feature that gives our customers more feedback on the choices they're making and lets them understand the differences in the product options that they're picking. The next thing that we're going to tackle is the behavior of the thumbnail images. So, at the moment, if I click a thumbnail image, I get a larger version of that opening up in a new tab, like this, which isn't necessarily a bad result but as a customer, I expect if I click a red thumbnail, I'd want the options here to change to match the thumbnail that I clicked. So, in terms of how we're going to implement this, we're going to do it in two steps, and the first step is going to be to add some markup to the thumbnail links themselves. So, if we find the thumbnail links here, we're going to add a special data attribute to the thumbnail image itself. So, we're going to call this data change variant. We're then going to specify the ID of the variant that this thumbnail is linked to, and so each image in Shopify has a list of variants that it may be related to. We're just going to take the first one of those and return the variant ID for that. So, to see what this actually looks like in our page, let's jump back to the browser, refresh, and then inspect these individual thumbnail links using the Chrome inspector tool, and we can say that each of these links does have a data change variant, data attribute and it's linked to a particular variant ID. Just adding these data attributes hasn't actually changed the behavior of our thumbnails, so that's what we're going to do now and set up an event handler to handle click events on those thumbnails. So, we're going to do that inside theme.liquid. Diving into that, the first thing we're going to do is actually when we're initializing those OptionsSelectors, we're going to maintain a reference to that option select and we'll see why in a second. But once we've done that, we're now going to add an event handler for click events on any elements with that data change variant attribute which we set up before. In the method for that handler, we're going to prevent the default behavior, so opening in a new tab, and then what we're going to do instead is using that reference to the option select, is we're going to call the select variant method, and pass it the ID of the variant that this particular thumbnail is linked to. So, let's save and have a look at how that works. Refreshing the page, and now, if we click a thumbnail, we should see that the option select is changing to reflect the values of the variant that that thumbnail is linked to. So, this is exactly the sort of behavior that we want. It's important to note that we didn't actually have to manually specify, in that click handler on the thumbnail, we didn't have to say, and now you need to update the featured image, or now you need to update the price, it actually just flows on as a consequence of how we set up our variant select handler. This to me demonstrates the power of the approach of building things up around this simple base option select is in the first place, setting up a good variants. Select call backed up, they view a page as needed, because then, we can add extra components later like these thumbnail selections, and all they need to do essentially, is send a message to the option select, saying, "I'd like to select this variant now." The logic that we've already implemented will handle all of the other updates to the page. Pressing on, let's think about what else we can do to make this page better for users. One of the things that I would identify is the select drop-down for the color option. So, select drop-down is good when you have a lot of options, and a user knows what they want to pick, so for example, a country. But for colors, you're probably better off displaying those colors to the users in the form of a swatch or something. So, what we're going to do now, let's see how we might go about tackling that. So, diving into the product template, we're going to add a little bit of liquid to do this, and when I say a little bit, I mean quite a lot. Unfortunately, this is a bit typical of a liquid. So, we're not going to dive into the details of this too much, but to give you the general idea, what we're doing is iterating through every option this product has. So, whether its color or size, finding ones that are related to color, and then based on that iterating through all of the variants that that product has defined all of the different colors that are available. Then for each color that is available, we output a link that has a swatch inside it. So, that's what this link here is, and we can say that it's outputting a style attribute that includes that color, and then much like we had the data change variant attribute on our thumbnail images, we now have a data change option, and data change value, data attribute. So, our approach here is actually going to be quite similar to the thumbnails, and that we're going to set up an event listener to listen to clicks on this specific type of link, but rather than changing the whole variant, what we're going to do is use the data change option and data change value, data attributes on our swatch links to change just the specific color that we're selecting rather than the entire variant. So, just before we preview what the liquid changes we just implemented look like, we're just going to add a little bit of styling to our style sheet to make sure that our swatches render properly, and then we're going to save that, and then check out what happens when we refresh our page, and we'll see that the swatches are rendered as we had hoped. Now, because we set these up as links pointing to particular variance as a sort of fall back, this will actually semi-work. If we click these links now, you'll see that the variant is being updated in the URL. But to get this working fully in the way that we want to, we're going to have to set up that JavaScript event listener in a similar way to the variance. So, dropping back into the theme.liquid where we have all of our JavaScript for the moment, we're going to add a second event listener which is very similar to add data change variant listener. But this time we're listening to a click on our data change option. Actually, I'm sorry. In the actual handling to that, again we're preventing the default action, and then we're extracting the type and value of the option. So, whether it's a color option, and then whether it's red, green, or blue, and then we look inside the existing select drop-downs that we have generated to see if that value exists, and if so, we're going to change that select box to that given value. To see how this actually works, we head back to the page and refresh. Now, when we select a different color options, we should see that only the color option is updating and that's being updated dynamically through JavaScript. So, now that we've got that working, because it may be it didn't make sense to have the lead option as a swatch style as well. Because, there are only two options and be useful to let users just select between those two. So, we're going to do that by basically generalizing the liquid snippet that we added to our product page for the color swatches, and just making it work with non-color options as well. So, we're going to do that by creating a snippets folder, and creating a new snippet. So, this is basically, exactly the same as the liquid that we added to the product template with this few slight modifications, the modifications being it'll render for all types of options, not just color options, but there is a check-in there to say whether the option is a color option or not. If it is a color option, then it's going to render this tile link with the swatch, otherwise, it's just going to render a regular text link. Now's probably a good time to reiterate, to not be too stressed out if you're not following along with every little detail of the code. At the moment we're just focused on the overall approach and ideas, and you're always able to read through the actual code in a lot more detail on the GitHub repository. Let's finish off here, and now that we've got our snippet set up, we can replace the code in our product liquid template with just an include of that snippet. So, that'll work for both the color and the non-color option. So, now we can save that will automatically upload to our store and then when we refresh, we can see that the lid option is now as same as swatch as well. So, users can now get a good overview of all the different options that are available for this product, and work in tandem between the color and lid selection to be exactly what they want. So, we're very close now to being done, but they're probably just two little things that we'd like to clean up before the very end. The first one is that, we only want to be showing the either swatches or the select drop-downs, not both at the same time, and we need to take into account the fact that the swatches aren't going to work when we have JavaScript enabled, so, we need to think about what's going to happen when JavaScript isn't enabled on our site. So, what we're going to do to handle this, is a pretty common pattern, we're going to add a CSS class to the body of our page, and remove that class when we have JavaScript enabled, and based on whether that class is present or not, we're going to be able to show or hide the different selection methods. So, we've added the class to our body, and now we just need to add a little bit of JavaScript into remove that class. Then once we've done that, we can jump into our style sheet and simply just add a little bit of styling to hide particular elements when we don't have JavaScript enabled. So, refreshing the page now, we can see that with JavaScript enabled, those select boxes are hidden, and we are able to use the swatches as normal, if JavaScript is not enabled, then we have this nice fall back to the simple select box which is a pretty but it does work. Okay. So, there was a lot going on in that example. But don't worry if you didn't quite get everything the first or second time around. The really important thing to get out of the lesson, is to see how the product page is built up in Shopify, and to also understand the advantage of taking this progressive enhancement approach. So, building each component up on top of each other, in a way that's independent, so that it's easier to maintain and reason about what's going on, on the page. This progressive enhancement approach of taking these little building blocks, and stacking them on top of each other so that they are independent, and that we get a page that works without JavaScript, and then slowly add functionality. This is an approach we're going to take in the next lesson when we start looking at collection pages.
5. Filtering, Sorting and Viewing Collections: In this lesson, we're going to be continuing our work with the demonstration candle store. But this time around we're going to be focused on the collection pages rather than on the product pages. But we're still going to be doing the same sort of thing, we're still going to be trying to help our customers make their choices more effectively and efficiently. Providing a better user experience. Once again, we're going to be doing that in a way that builds up our knowledge and understanding of how the Shopify pages are put together from the ground up. This is an example of collection page from our demo candle store and what we're going to be doing in this lesson, is adding ways for customers to drill down and find the products that they're really interested in. So, things that you will have seen across a lot of Eagle Nest stores before, things like, being able to change the way we view products, being able to sold products, being able to filter them. While we're doing all this, I think it's important to keep in mind that the goal of these collection pages is always to make things easier on the user, to drill down and find what they're looking for. So, we're going to start by allowing customers to change the way they view these products. Whether as a grid or in a list where they can see more detail. Let's take a look at the HTML we are starting with. If we open up the collections template, we'll see it's pretty straightforward, we have a title, we have a section called collection products which is where the actual products are being displayed, and then we have an empty section called collection controls, which will be where we put the elements that will allow our user to control what they're saying. So, we're going to start giving the user the ability to control the view by wrapping the entire page in a form and we'll see why we're doing that in a second, and then we're going to add some HTML to the collection controls, and that's going to consist of a select dropdown, which gives us the ability to choose what view, and then we have a submit button, which calls an update. So to see what effect that actually has on our page, we'll say that we now have this very simple select control, and we can change between a ListView and a GridView. So, that we're not actually changing anything on our page, but you will see that it's changing the URL and adding this view query parameter. To actually do anything with this query parameter, we're going to have to use a feature in Shopify called alternate view templates. So to do that in our templates directory, we're going to create a new template and we'll call it collection.list.liquid, and then we'll just add some random HTML content in here to see how this works. Save that, and then if we go back to our browser, we can say that if our view parameter is left as grid, then we get what we originally had, but if we change it to list, the ultimate template is rendered with the content we just created. Let's do something a little more useful than this. So to begin with, we're going to have some common functionality between our grid and list views. So, we're going to extract out current collection page into a snippet. We will call this collection view, and we'll just copy over what we've got in our existing collection template into there. Now in our collection.liquid, we're going to include that snippet and we are going to say that our default view should be a grid view. So, we'll include it with grid as a parameter to that snippet. Then on our alternate list view, we're going to include exactly the same thing, but just change the parameter to list. So now that our snippet is being included in both templates, we can adjust it to handle both grid and list views and we're going to do that by adding a CSS class and now putting the name of the collection view snippet, which will be populated with either list or grid, depending on where we're including it from, and we've set up some CSS styles to render it differently based on the value of that. So now refreshing our page, you will see that if we have the list view handle, we're going to see the products as a list, and if we leave it as grid, then we'll see them rendered as a grid. So, that's a simple view implementation. Now, let's turn to sorting and this is where we will see the advantage of having this form-based approach to updating our query parameters because all we really need to do to add sorting into our form is to add this select element with these option values in here. So, we just name the select value, select the element sort by and the options we put into it are the predefined sort parameters that Shopify lets us sort our products on. So, simply saving that and jumping into the browser again, we can say that we now have a sort by select drop-down, as well as the view and we can mix and match our values here to change the way that we're looking at our products. So, this form-based approach is nice because it means that we don't need JavaScript to update the way we're looking at products, and it also means that all of the information we need to recreate the view we're looking at is there up in the URL. Our next step is going to be letting our customers narrow down the products they're interested in through the use of filters. Now it's important to note, that on Shopify, we really have two levels of filtering. We have collection level filtering and tag level filtering. So, we'll take collection level filtering first and that's basically, just narrowing down the products we're interested in based on what collection they are in. We're going to take the simplest approach to implementing this, which is to simply provide a list of links to each collection that we'd like to filter on. So, we've just added this list element to our collection controls and at the top, we have a list element that contains a link to the old collection, which is a special case, and then for every other collection in our store, we're going to render a new list element and inside that list element, we're going to render either a link to the collection or if it's the current collection, we'll just render a span. Seeing this in practice, we'll refresh our page and we'll see that as expected, we have a list of links to all of our different collections. So, clicking on those is going to take us to the URL for that collection, as you can see up here, and on top of that we're then able to change our view and sorting parameters to adjust the view appropriately. To let users drill down even more specifically into our collections, we can let them filter based on the tags that products have. Again implementation wise, we're going to keep this pretty simple. So, like we had with our collection filtering, we're going to have a list of links that we can use to filter on tags. So you can see here, we've got our unordered list, and then we're going to iterate over every tag inside of the collection, and for each of those tags, we're going to render a link either using the Shopify link to remove tag or link to add tag filters. These are useful liquid helpers that Shopify provides is for exactly this purpose. Seeing how this looks on our store front, we will see that after refreshing, we now have our tags listed as links and we can toggle them on and off as needed to filter out collection further. You'll also notice that the list of tags available changes based on what tags are present inside the category. So, that helps customers narrow down to only relevant tags. As before, we can apply view and sort adjustments and everything's gets for us in the URL. So, we've only got a couple more features to add before we have a pretty functional collection page and one of those features that we are missing still is pagination. Fortunately, our simple form-based approach is going to make adding this relatively easy. Looking at the HTML for our collection page at the moment. To paginate anything, we need to wrap it in this paginate tag which we then pass the list of items we want to paginate which in this case are the products in the collection, and then a number of how many items we'd like per page. So, we'll start with three. Usually, you'd have something a bit higher on a real page but this will let us see the pagination in action. I'm also going to include this pagination snippet here and that will render the controls that we use to paginate. I'm not going to go into too much detail on the actual content of this code as you can find this both on the GitHub examples for this lesson and in the Shopify documentation. Taking a look at the result of our handiwork you can see that we were immediately cut down to three results on the page and we have this pagination which down at the bottom here, and we can move through the pages in our results and the URL is kept up to date in line with that. I want to point out here that all of the state information about our page, so what collection, what filters we apply, what view state we're in, how we're sorting the products is all in the URL. Which means, not only that we can copy and paste that URL to get back to exactly the same position, We can refresh the page and get back to exactly the same position. But also, if we turned off JavaScript, our page works in exactly the same way. I think that that property is really important in Shopify themes because even though lots of people aren't browsing the web without JavaScript these days, there are situations where the JavaScript doesn't load because of an error. Or it doesn't run because of an error but also for users on slow, say mobile connections, often they might be interacting with your page before JavaScript has a chance to kick in. So, having this base experience, making sure that our pages are progressively enhanced, really improves the user experience and avoids losing sales. Now, that's not to say that there aren't ways that we can use JavaScript to make the customer experience better for those who are using it. So for example, at the moment, we need to hit the update button after we select our view and our sort options, let's improve that experience by making the form auto submit when a select box is changed. To do that, we're going to add some JavaScript to the bottom of our theme.liquid. So normally, you'd put this in a separate JavaScript file. But for the sake of argument, we'll put this in here. And so this bit of JavaScript has a check to make sure that it's only executed on collection pages. And then we're setting up an event listener on a change event on any element with a data update collection, data attribute. And then in the handler for that event, we're simply submitting the form that the element lives in. So, let's make sure that our select elements do indeed have that data update collection, data attribute, and once we save that and refreshing our page, we should now see that if we change the select boxes, we're automatically submitting the form and our view is changing. That's great but it also means that we now have this useless update button, or at least it's useless when we have JavaScript enabled. So what we're going to do is use a common pattern to hide this button when we do have JavaScript enabled, and only make it visible when we don't have JavaScript available, and we actually needed to submit the form. So, you can see here in the theme style sheet that we have this js-hide class which is going to hide things if we have JavaScript enabled. But then, show it if we don't. So to make sure that the right classes are applied, we had the no js class to the body by default, and then we simply remove that using JavaScript. So, at the bottom of the page, we'll just add a little bit of code to turn that class off if we do indeed have JavaScript enabled. So, looking at this in action, we're going to save, refresh that browser, and we've got JavaScript enabled at the moment and we'll see that that button is indeed hidden but I can still change my view and my sorting options. That's working fine. But then, if I turn JavaScript off, we now have that button, and are able to use it as normal. So, while we're in the process of adding JavaScript functionality to our collection pages, let's take a look at adding ajax so that customers are able to move through our collection pages without having to do a full page refresh. Personally, I find that the perceived advantages of ajax powered pages a little bit overstated. Especially when you take into consideration the extra complexity in implementing them. But there can be some advantages and thankfully, in our case the way that we've built up our forms to date means that adding ajax functionality is actually reasonably straightforward. So our approach for this is going to start with adding an ID to the form that we're using, and that's so we can refer to it in JavaScript. Our strategy is basically going to intercept the submission events on this form and to make that regular form submission event into an ajax request. So, that's what we're going to do with this JavaScript here and walking through it, we can see, as I mentioned, we're capturing the submit event on that collection form. We're preventing the default action on that form which is to submit as a regular form, and then we're using jQuery's load method which is a convenience around sending an ajax request fetching some HTML contents and replacing it in our current page. So in this case, it'll be replacing the content of our page with our updated collection view, and we've also got a little bit of code here that's triggered on the successful rendering of that content using pushed states to keep the URL bar of our browser up to date. So, this simple approach is all we need to actually use ajax with our collection pages. So, if I refresh the page here, and now anytime I perform an action that resubmit that forms such as changing my view. My page is actually reloading via ajax. So, we can check that that's actually happening by opening up the Chrome developer tools, checking network panel and then we'll see if that as I change this select boxes. It is in fact performing a single ajax request and not a full page reload. Now, the astute among you may have noticed that while this will work for any action that triggers a form refreshed like mutating the select boxes, how collection links while they'll still work desktop performing a full page refresh every time we click on them. So there's actually a solution to that as well, and it's pretty similar to how we handled the form submission. So you'll see, our filter linked here already have a data link collection attribute, and so our solution here is going to be to simply add a listener to the click event for anything with a data link collection attribute. Again, prevent difficult action which is to follow the link and then use the load method again to load in the destination of that link as our page content and again using push state to keep our URL updated. So, to take a look at how that works, again, we can open up the Chrome developer panel to check that we're actually making ajax requests, and now we can say that when we're clicking these links, we are in fact performing a single ajax request rather than a full page reload. Of course, thanks to the way that we built this up with progressive enhancement we can turn off JavaScript and still have a fully functional and very, very usable collection page for our customers. Again, there was a lot going on in that lesson. But I really want to stress. Don't worry if you didn't get some of the more technical aspects there. You can always head over to the GitHub repository. You can check out the code examples there. They're well commented, and that should make it a little bit easier to understand. The important thing to understand is how the Shopify pages are put together from a basic level, and how we can use those individual components together to build a really functional and usable page.
6. Adding Ajax to your Theme: If done correctly, adding Ajax powered functionality to your theme can be a really great way to make it feel a little more responsive and easier to use for customers. And it's probably something you will have seen in a lot of themes these days. In this lesson, we're going to look at the best way to start adding Ajax powered add to cart functionality to our collection pages. So, we're back on the product page and this time around, we're looking to make our customer experience a little bit better by adding Ajax cart functionality to our add to cart button. Ajax functionality can make our product pages feel a little more responsive and they can also avoid our customers having to perform repetitive tasks like re-configuring a product if they want to order multiple versions of it. Like we did in our previous lesson with collection pages, we want to make this progressive enhancement. So, let's take a look at what's happening with our product pages at the moment. So, we're able to select our product options, add a custom message, and then when we click "Add to Cart," we're making a standard post request to add that product to our cart and we're redirected to the cart page. So, what we're going to be looking at in this lesson is how to change that interaction so that when we click the "Add to Cart" button, we're actually making an Ajax request to add the product to the cart with the choice and options without redirecting the user away from the product page. So, let's start by looking at Shopify's documentation for the Ajax or API that they make available to see an idea of what's possible with it. So, you'll see in the documentation they've got some useful information about it, but we're mostly interested in here is these possible requests. So, you can see here that we're able to fetch information about products, we're able to add new items to the cart, grab defection information about the current cart, and we're able to make post requests to update existing items inside the cart. So, our strategy to progressively enhance this interaction is going to be to intercept the form submission when we click the "Add to Cart" page using Drae query and then instead of a regular post request, we're going to take the same data in that form and make an Ajax request to add the items to the cart. Let's dig into our theme code. So, if we open up our product template, we'll see that we have our form that we're going to submit the submission of. It has an idea of product form and we'll use that in our JavaScript. In the actual JavaScript, we're going to use to turn this into an Ajax request, we're going to add to the bottom of theme LIQUID, which is where we've been putting most of the JavaScript to date. In a real theme, as I think I've mentioned before, we'd want to put this into a separate JavaScript file here in the assets directory. But for now, we're just going to keep everything here so that it's easier to keep a mental hold of. So, when it comes to the actual JavaScripts, we're going to as we mentioned, we're going to add an event listener to the submit event for that form and we're going to prevent the default action, which is to submit that form as normal. Emulating the form post is done with the $.post method our endpoint is /cart/add.json and we're going to passet the data parameter that's gotten from serializing the form. So, $(this) refers to the form itself in this instance. So this should be actually all we need for the initial parts and functionality. So, if I go back to my cart page and refresh and make a couple of selections and message my products and hit "Add to Cart" it's going to look like nothing actually happens but that's because the form submission has been intercepted. And so if I go to my cart, you'll see that this product was actually successfully added. So, if we want to double check that that happened through Ajax and not through some other form or magic, we can use the chrome developer tools to inspect the network requests that are actually getting made. So, if we make another selection punching a message and then when we hit "Add to Cart" we'll see the actual add Ajax request coming up and we were able to inspect the details of that through that panel, we can see the form data that's being passed, and we also see that the response that comes back is a JSON representation of the line item that was just added. Of course, our whole motivation in adding Ajax is to make this more usable for our customers. And what we've actually done is made it less usable because we're now providing pretty much zero feedback on the fact that something is being added to cart. So, let's take a look at how we can fix that. We'll use a pretty common pattern here and that's to change the text of the "Add to Cart" button and disable it when we start making our Ajax request, and then when it's done, we're going to change that back. To do that we're going to use these callbacks that JQuery gives us access to. We have done, fail and always. These are part of JQueries promises interface. So, done the callback done, will be executed whenever an Ajax request is successful. Fail will be executed and this is since when we get an error response and always the callback there will always be executed at the end of an ajax request. So, in our use case, we are always going to want to restore the "Add to Cart" button to its original state. So, we're going to put that in the always callback. So, this will execute no matter whether the request is a success or a failure. So, saving that let's see the impact that that has on our pages. So, refreshing our page and setting up our product options. Now, watch carefully when we hit "Add to Cart" here and you can see that the behavior is as expected. This is a good start but we still need to give a bit more feedback when things add to cart. So, for example the cart total in the top right corner isn't being updated. So, we're not 100% sure that something has been successfully added and it also would be nice to make a check out link appear as soon as we add it to cart. So, just to reassure users that their change has been registered as well as encouraging them to take a next step. Tackling the updating of the cart information in the northbar first. When we successfully add something to the cart. So, in the done callback, we're actually going to make a second Ajax request to the /cart.json endpoint which gives us an updated version of everything that's in the cart at the moment. When that Ajax request completes, we're going to use that cart information to update the nav-bar cart HTML element which we can see is up here in our header and we're going to update that with this text, the word cart and then a formatted version of the total price of the cart. That handles our updating issue. While we're here we're also going to just quickly add a little bit of error handling in the fail case. So, this is going to be very basic just adding an alert message with the error this return from Shopify. In a real scenario, you'd want to inspect these a little bit more and provide a useful message to the user. Let them know exactly what went wrong. Onto our next task, which is to make that checkout link appear when we've successfully added an item. So, we're going to add to that checkout link as an HTML element underneath our "Add to Cart" button. You can see it's an ID of check out link. It points to the check out and we're going to make it initially hidden with style display none. Back to our theme.liquid JavaScript and we're just going to add the logic in here to make that check out link visible at the completion of a successful add to cart operation. Then we're able to test and see if things are a little bit better. So, refreshing our page. Then when we go through the process of selecting our options, adding a message. As you can see, both the cart in the nav-bar is updated and we've also got that check out now link appearing. That's a really easy way to add a progressively enhanced Ajax cart to your product pages as we mentioned before in a real world scenario, you'd probably want to provide users with a little extra feedback both in error scenarios and let them know exactly what's gone wrong if something does go wrong. But also in the success case maybe make it a little more obvious here that something has been successfully added to your cart and always thinking of the next steps that you want to user to take whether that's add another product, reconfigure a product or to start the checkout process. Having gone through the process of seeing how we'd manually set up Ajax cart functionality, we're now going to look at a library that does most of the work for us which is Cart.js. Now I have to offer a little disclaimer here that Cart.js is a project that I've authored myself but it is 100 percent open source and free to use for all theme developers. Back to our product page, which we have reset to pre-Ajax behavior. We're still going through the regular post to cart redirection flow here and we'll have a look at how we would implement Ajax functionality using Cart.js. First step is to head to cartjs.org and download the latest version of the library. We can do that as a zip file. Then once we've done that, we just want to extract the zip file and then grab the library as a javascript file, minified javascript file and we'll drop it into our theme's assets directory. So, if we just check in our text editor, we can see that that's been copied across. To actually start using cartjs in our theme, we need to add some initialization JavaScript to the bottom of our theme.liquid and we also need to include the library as well. So, we're going to do that using an asset URL and a script tag and then we call these initialization function and pass it the initial state of our cart. From here, we just need to add a little bit of markup to our theme to indicate what we'd like to do with cartjs. So, we can add a data cart submit attribute to a form and that's going to emulate the form submission functionality that we implemented manually previously. Then we can also wrap a display element with a data cart render attribute. We're just going to emulate the update function that we had in the nav-bar. So, with the addition of just those two attributes, we have actually replicated a lot of the functionality we just build out manually. So, we can see here the form submission is captured and we are automatically updating the cart in the nav bar. That was a pretty whirlwind tour of cartjs. There's a little bit more to the library than that but that's what we really have time through for in this lesson. So, we'll leave it there and if you're interested in it you can check it out on the cartjs home page. That's it for this lesson. Hope you've got a good understanding of how to start applying these Ajax techniques to your theme and also that you understand the importance of taking that progressive enhancement approach where we build up the basic functionality first and then later the Ajax on top of that.
7. Best Practices: Now it's time to talk about everyone's favorite topic, Best Practices. I know it's not the sexiest of topics but it can be really important to build your themes in a way that makes it easy for yourself and others to maintain. So if another developer comes onto your projects later on, they want to build an integration with your theme, or even just if it's yourself coming back to your theme six months later, and you don't have any recollection of what your theme was doing or what your code was doing, following these best practices makes things a lot easier to pick up and get going. Let's start off by looking at liquid which is one of Shopify's most unique and defining features. In this example, the theme we're working with has a product page which is written in liquid as all of our templates are. Down in the bottom part of this product page, we have a related products section, and that uses a bunch of liquid to generate a list of related products. A useful thing to do when we have lots of large complicated liquid, is to extract it into a separate snippet. This keeps it a little more manageable for us and it also lets us reuse that code in other sections. So we may want to reuse this liquid snippet elsewhere. So here we've cut it out of our product template, and we're including that snippet, and we're going to dump it back into the related products snippet here. Now when it comes to the actual liquid code itself, one thing I see that people just fail to do with liquid a lot of the time is add comments. I really can't stress enough how useful adding comments in liquid is especially when you've got complicated stuff going on. It's not only useful for future developers who might pick up a project after you but also to your future self because in two months time if you come back and look at liquid code you've written, you're not going to remember the intimate details of it. Two, final quick points. It's really useful to make sure that your code is formatted well so indented, easy to read again for the same reason as adding comments is really useful. Just a final note and that's on nesting snippets. So, as you can see at the bottom of this snippet, we're actually including another snippet, the product snippet. I'd say that two levels is about the maximum you want to go with a Shopify theme and nested snippets. Any more than that and it becomes a little bit difficult to mentally reason about what's going on in your code, and it becomes a bit of a tricky maintenance issue. Moving on, let's talk about Stylesheets. A lot of the best practices for Shopify stylesheets are going to be exactly the same as they would be in regular web development. So, adding comments always useful both for yourself and for other future developers. Something that is unique to Shopify though is its support for the Sass preprocessor. So it pays to be familiar with some of the tricks and methods that you can use in that language. So for example, the @extend directive as we're seeing here. Another thing unique to the Shopify contexts is that we can use liquid to output values from our theme settings inside our style sheet files as we're doing here. However, we can run into a little bit of a problem with the liquid here because the liquid tags themselves are not actually valid Sass. So this can cause problems if we're using outside preprocessing or if we're just simply using syntax validation. So what we can do is what I'm doing here and that's to add a string escaping function which is valid Sass, but well also still render your liquid template variables inside your style sheet file;. So that should avoid the problems that I just identified. Let's turn now to JavaScript which is actually one of the areas that I see most problems with in terms of maintainability and performance in Shopify themes. So if you recall how we wrote most of the JavaScript in earlier lessons, we put most of it directly into the bottom of our theme.liquid. That's not really the best practice. So what you really want to do is extract as much of that JavaScript as possible and place it into separate JavaScript files in your assets directory. This is better for maintainability and it also means that browsers are able to cache your JavaScript instead of having to load it with every page load. It also means that your JavaScript files are available to perform preprocessing on, you might want to minify or concatenate them before you deliver them into production. Now the downside to extracting your JavaScript into asset files is you are no longer able to access liquid code that is available to you from within your theme templates. The best way that I've found around this problem is to create initialization functions inside your JavaScript and pass your liquid objects in configurations through from your template files. So to see how we might do that here, we'll create a setup a product page initialization function which expects a product's json object which we can no longer render from liquid inside this JavaScript file, and then we'll just do a little bit of code cleanup to make this work with our new initialization function. We can see here the liquid code that we were using that we can no longer use, so we'll just pass the product variable into it there. We'll just clean up the ones on this code a little bit so it's a bit more readable. From here the task is simply to be able to pass that product variable to that setup function from the theme liquid. So we can do that by making sure firstly, we've included our new JavaScript file that we've just created. Once we've done that, we can just use this one line of JavaScript here in now liquid templates to pass that liquid object through to our initialization function. Unfortunately, we don't have the time needed in this course to dig really deeply into what makes best-practice JavaScript for a Shopify theme. But I think there are three key things that you can think about that will help you write JavaScript that's easy to maintain and very professionally known. The first one of these is to write your JavaScript defensively. What I mean by that is write it in a way that doesn't make assumptions about the page it's being loaded on. So, don't assume that a DOM element is going to exist on the page because your script might be loaded on the product page, or the collection page, or an index page, and you may not necessarily have control of that. The other aspect of writing defensive JavaScript is to make sure that your script plays nicely with other third party things that might be installed on the page. If something goes wrong with another script, then hopefully you can work around that and write your JavaScript in a way that doesn't depend on other people's stuff working correctly 100 percent of the time because it just doesn't happen. The second thing I think is really important is to write your JavaScript in a modular manner. So, breakdown your JavaScript into modular components that have their own individual areas of responsibility. That way, they don't depend on each other, it's a lot easier to maintain, it's a lot easier for other developers to come along, understand what's going on, reason about, and then further develop those modules. The third thing that I wanted to talk about around your JavaScript is to make sure that it's written in an event-driven fashion. What I mean by that is that when for example you're variant changes on a product page rather than having one long function that has a prescription for all the different things to update on the page, instead trigger a variant changed event and then you can have all your other components hook into that events and update their own area of responsibility independently. So, for example, you might trigger a variant updated event and you might have one component that updates the price of the product, another one that updates the featured image of the product. That way you keep things very separated as similar advantages to when you're breaking down your JavaScript into modules. This latter point, this event in JavaScript, becomes really important when you start getting really complex themes that might deal with things like different currencies, different languages, different locales, because you can have a whole bunch of different inputs and it makes it a lot easier if you only have to worry about updating individual components on a page, you can reason about it a lot easier. Another topic that we don't have time to cover in depth is theme performance. That's a bit of a shame because I think that performance is a topic that really doesn't get enough prominence when we're talking about Shopify themes. Yes, I realized the irony that I'm saying that we don't have enough time to talk about it when I think it's a shame that we don't talk about it enough. The fact is, performance really does affect your conversion rates. So, Google has done a study and an increase of one second in your page load times can result in up to seven percent drop in conversion. So it is something really important. The question then becomes, what can we as theme developers do about it? The first thing I think that's really important to have is a way of measuring your theme performance so that you have some idea of whether anything you're doing is actually making a difference. There are two tools that I think are really great for this. The first one is Google PageSpeed Insights. That's a really simple tool that Google gives you. You can plug in a URL, you'll get a breakdown on where the big ticket performance items or big ticket issues are for you. The second tool that's really great is WebPagetest.org. It goes into a lot more depth. You get waterfall charts, it gives you a breakdown on all the different individual components on your page, and it also has this thing called the speed index. The speed index is a measure of how quickly a page becomes usable for a customer rather than the time taken for the whole page to load, and that's usually a more important thing because what customers really care about is how quickly are they able to interact with your page rather than when the very last JavaScript widget loads. Now, in terms of what you can actually do practically to improve your theme performance, there are a couple of big points that I'd start by tackling first. The first one of these is top loaded JavaScript. So, a lot of the time if you look at themes, they load a lot of libraries including say jQuery in the head of the theme. Moving those those libraries from up here to the very bottom of the body of the page can have a huge impact on load times as the browser doesn't have to download parse and execute all of that JavaScript before it even starts showing the content at the top of the page. Another big performance killer is unoptimized images. So if you have JPEGS or GIFS or PNGs in your theme that haven't been properly optimized, you can be sending a lot of unuseful bites down the wire. You can use tools like ImageOptim or ImageAlpha to optimize these images before they go up to your theme, and you can also bundle those into an automated theme development process as we'll see later on. Another thing to look out for is to make sure that you're serving the right sized image to the right sort of devices. So there's no point loading a 3X retinal image to a mobile phone that isn't going to be able to display those pixels, and likewise, there's no point serving a high-resolution image to a desktop device that doesn't have a high resolution display. So there are a couple of things you can do to make sure that you're doing the right thing there. You can use JavaScript libraries to make sure that the right sort of image is selected, and for newer browsers which is where this is most applicable, you can use the new source set attribute on images. Finally, and this is really the toughest thing to do with your theme but also the most useful, and that's just to remove stuff. So, if there are components on the page that are really slow to load or taking up a lot of download or bandwidth, then just consider if you can replace them with something that's a bit lighter weight. A great example of this that I say all the time are carousels. So carousels are horrible from a usability perspective. Users just don't tend to move to the second or third slide, or they get frustrated by them when they want to go to the first item in the slide, and it slides past that and then they want to try and get back to it. So, carousels are just bad usability, but they also load more images than you might actually need. So replacing a JavaScript carousel with a single image can be a great way to both improve the usability of theme but also dramatically reduce the amount that needs to be downloaded for your theme in the first place. The're are my top tips for performance and making sure that your themes load a bit quicker. If you're really interested in this topic, I've written quite a bit about this on my blog, gavinballard.com where I dive specifically into the use cases around Shopify themes and performance optimization.
8. Automating Your Workflow: In this lesson, we're going to be talking about workflow automation. So, the process of taking repetitive tasks and automating them. We get a lot of benefits from doing this. The most obvious one, is that we save ourselves a lot of time. So, we don't have to perform the same manual step again and again. But there are a couple of other ones as well. We get more flexibility in how we can structure our projects. So, instead of having to package things up, how Shopify expects the final theme to be, we can structure things out in a way that makes it easier to maintain, split out our JavaScript files for example and compile them together. We also make our deployment process a lot more reliable, because it's automated, we don't have to worry about forgetting a step if we're doing things manually. Then, the final advantage that we get from this, is that we have some form of documentation of our deployment process. So, whereas, before we didn't really have any way to communicate our deployment process into another developer, for example. It may have just been written down in a Google Doc or we're just trying to remember it. By automating the process, we have some form of documentation of that process in the code itself. In this lesson, we're going to be looking at one specific tool for workflow automation called Grunt. Grunt is based on Node.js, it's quite a popular and common framework and I like it, because it has a really large ecosystem of plugins. So, if there's any sort of tasks that you might want to do with your Shopify theme, whether it's concatenating files, minifying style sheets, or optimizing images, there's probably already a plugin for Grunt that does that. We'll be taking Grunt in this lesson and seeing how we can apply it to the process of building Shopify themes. The first thing to check, is that we have both node and node package manager installed on our machines. If you don't have that setup, then, you can look up on the node and npm website on how to get that sorted. Once, we've done that, we can run this npm install command to install the Grunt client library. That will give us access to the command line tools with Grunt. Once, this is set up, we're in our theme directory. The first thing we want to do is run npm, in which creates a package.json file. If you're familiar with node projects, you will have seen this before. If not, it's basically just a way to list all of the dependencies for our particular project. So, it's where we're going to pull in all of our Grunt plug-ins and things like that. So, I'm moving through the setup steps rather quickly. If you're not following along 100 percent, don't stress too much. You can always read up more about this on the Grunt website and also in the course materials. So, at this stage with our demo theme, we've got our dependencies for Grunt installed. We've got Grunt and a package.json set up. Now, we just need to look for something to actually do with it. Our demonstration theme for this lesson is the LaunchPad theme, which comes by default with all Shopify stores. If we dive into the assets directory for this theme, we can see that there are quite a lot of jquery plugins that this theme pulls in by default and that's quite a common thing to see in a lot of Shopify themes. But the problem with this, is that we do have to load all of these JavaScript files individually, so we're making extra HTTP requests. So, what we're going to be looking at in this lesson, is how we can use workflow automation to keep these files separate in development, to make it easier to manage. But bring them all together, concatenate them all together, so that we only have to deliver one actual file to the browser. Fortunately, for us, Grunt has a plugin, that does what we want pretty much right off the bat. It's called grunt-contrib-concat. So, we install Grunt plugins using the npm install command. If I had save-dev at the end as an argument there, that'll make sure that it's added to our package.json, so that, our dependencies are clearly listed. So, we just need to wait a little while for that install to take place. Then, if we actually inspect the contents of our package.json, we'll see that that new plugin has been added into our dependencies list. Now, if we inspect the contents of our theme folder, we can see that installing npm and node in Grunt has added this node_modules directory to our theme. If we run a git status, we'll see that git is picking it up as a directory that we may want to add to our project. We don't really need the node modules folder in our project, because all it contains is the dependencies that are listed in package.json. So, it's not really relevant code for our projects, so, we should add that to our gitignore. So, that we're not accidentally committing stuff, that we don't really need to be. We do however, want to make sure that the changes to the gitignore and the package.json itself are documented to our gitrepository. So, we're going to do that now. Now, we've got all of the components for running Grunt tasks together. But we still need a way to define what those actual tasks are and how they should operate on the files in our theme. We do that using a Grunt file. A Grunt file is a JavaScript file that sits in the top level of our theme directory and it's where we define all of the automated tasks, that we'd like to be able to run on our theme. So, if we take a look at this example Grunt file, we can see that it is a JavaScript file. So, it just uses regular JavaScript syntax. So, it has an exports line at the top and then, we define our tasks within this grunt.initConfig call. So, you can see here, I'm passing a hash that defines a few tasks including this concat task. I'm giving that task a name and then, I'm defining the source files that I want to concatenate together, and the destination file for where I want that all to end up. Down the bottom here, I have two lines. One to load the concat plugin, and then the second one simply registers that concat task we've defined as the default task. So, how that actually works when we want to run these tasks? If we jump back to the command line, we can run grunt concat. As you can see, it'll tell us it's run that task and that it's created this jquery plugins file. So, if we want to take a look at what that looks like, we can see that the plugins file has been created and as expected, it is a concatenation of those other jquery plugin files that we defined. So now, all we've got left to do, is to replace those individual imports of those individual jquery plugins with the single import of the single call to a script tag for the concatenated file together. Once we've done that, we can just remove these existing calls. What we just did was a really simple use case for Grunt just concatenating to files. But we could have been doing a lot more, we could be midifying those files before they got pushed into production. We could be performing some syntax checking on the JavaScript, to make sure everything was okay and error-free before going into production. We could be optimizing images and on top of that, we could be doing that in a different way depending on what environment we were in. So, whether we were in development or in production. But of course, Grunt isn't the only tool that we can use through this sort of thing. There are other tools, things like Gulp or CodeKit, that effectively perform the same process. But the actual choice of tool that you use, isn't really the important thing here. It's just that you have some form of workflow automation, to get all the benefits that we listed at the start of the lesson.
9. Deploying Shopify Themes: Like the previous lesson, this final lesson is all about our deployment process and specifically we're going to be talking about deployment, how we get our code from our development machines into production, in Shopify in a professional and efficient manner. Let's start by getting an overview of deployment methods and how we've been doing things to date. When we set up the theme gem in the earlier lessons of this course, we were using it to essentially deploy directly to our live theme on our Shopify store. This works fine for development but there are a couple of issues when this becomes a live production store. The first one is that your developers are pushing changes directly into production without any real preventative measures to avoid accidents. You're not really having any way to test new features. You also have difficulties in knowing what sort of state your live theme is in on your production site and you don't really know what version of the code is running, and using this sort of method also makes it really difficult to collaborate with other people on your Shopify theme, because it's very easy for multiple developers to overwrite each other's changes and it's very difficult to roll back to an earlier state if something does go wrong with that. So, one way to try to resolve some of these issues is to have two themes running on the same store, a live version and a development version. So, we're still using the theme gem to update changes directly to the development theme while we're developing and then once we're happy with the changes we've made, were able to deploy those changes to the live theme. One way to do this would be to duplicate the latest version of our development theme and publish it as a live theme on the Shopify store and do that through the Shopify admin. But there are a couple of problems with that. Firstly, it's still a very manual process so, there is the room for human error. It's also very difficult still to know what state our live store is in, so we're not really sure which of the latest development versions has been published and it doesn't really fix our collaboration issues. So, imagine the better approach is to continue using the theme gem to upload directly to the development store, but then to also use the theme gem to deploy to the live theme once we're happy with the state of the theme on our local development machine. This sort of avoids a little bit of the mucking around with the Shopify admin deploy process. But again, we still have these problems where we still using a manual process and we still have issues with collaboration as where uploading our theme directly from one developer's machine to the live store. A much better approach we can use is to continue using the theme gem to upload to the development store, as that's really the most instantaneous way for us to get feedback on development as we're doing it. But then to introduce the concept of a third party repository. So, this would be a code repository service, so something like GitHub or Bitbucket or GitLab or your own internally hosted Git Server. Once we're happy with the changes that we've made with our theme locally, we can just do a Git push to that repository. Then we can use a deploy service to take the latest version of our theme code and push it out to the live theme on our Shopify store. So, bringing in this concept of a third party repository between the developers and the production environment gives us a lot of advantages. So, we instantaneously get all of the collaboration benefits of using a central Git repository, so things like having conflict resolution handled for us. We can use whatever mechanisms particular Git hosting service has so for example. Pull requests, emerging pool requests and raising issues and things like that. We're separating developers from deploying directly to the production environment directly, which sort of minimizes the risk of having mistakes, and by having this deploys service step automatically deploy from our code repository to the live site. We open up the gate for things like automated testing during that stage and only deploying if all of these tests have passed. So, realistically, we'd probably have three or more themes on our Shopify store. So, a staging theme as well and then one Dev theme for each developer are not same, and then our deployment service would be automatically deploying the latest version of our code to the staging theme where it can be tested and then once it's passed a QA process we can trigger a manual deployment through that deployment service deal to the live theme that customers are saying. To go one final step further in a realistic scenario. Because it's bad practice to have your production site running on the same Shopify store as your staging and development themes, because you can't separate data like orders and customers. What you actually want to do is run two separate Shopify stores and so your deployments service can still be automatically deploying to the staging theme on your development store and then when you're triggering that manual deploy, that's going to the live theme on the production store. There are quite a number of services that will let you deploy code from a Git repository to a Shopify theme, and of course if you have got some back-end system development shops you can always roll your own. Today we're going to be looking at one specific tool and it's the one I like to use, it's called DeployBot. You can find that at deploybot.com. The reason I like it for Shopify theme deployment is that it has native built-in support for Shopify themes. So, it's really easy to get up and running and it also has support for some more advanced features like running a build script as part of the deployment process. Let's see how we can go about deploying a theme using DeployBot. So, we're back on our demo theme and if we jump into our photo we can see that I've got a config gambles. So, I have the theme GM setup to upload to the store and I've also placed this theme under Git revision control. As a first step for this example I've also pushed this theme to GitHub, so I have it hosted in a central repository. Now, let's see how the DeployBot fits into the mix. You can create an account for free with the DeployBot and use up to one repository with that plan and then once you've logged into your account you are presented with this, which basically steps you through the process of connecting a repository to your Shopify store. So, as you can see here, you can hook up GitHub, Bitbucket or your own self-hosted Git repository. I'm going to select the repository for this demo theme and hit Connect. Then on the other side of things, I need to create an environment, so that's hooking up to where we're deploying to which, in this case, is going to be a Shopify store. So, I just need to give that a label, specify how I want to be deploying to that environment. In this case, I'm going to leave this manual. I'm going be deploying the master branch, and then we can see that we're asked at a server. Then, we have this option to link indirectly to Shopify. So, choosing that, I just give that a name and the URL to my Shopify store. Then, we can hook in directly. So, the webhook basically sets itself up as a custom app inside our Shopify store. Just need to give that a name and then we can choose which theme we want to deploy to. So, we've got one in there called Product Customization which we'll use. We have a bunch of advanced options which we weren't dig into just yet. So, that's actually all of the configuration we need to set up in order to get a basic deploy service operational. We can now hit the Deploy button and DeployBot will fetch the latest version of our code from GitHub. It gives you the chance to review what changes are actually going to be deployed and then we can hit the start Deploy button to push that information, and push that theme and those files to our Shopify store. Now, if we refresh our Shopify store at the moment, we're not going to see any changes because of course, we were pushing the most recent version anyway. But let's see how we go through the process if we make a change. So, let's decide we want to change the color of our navbar and so we make that adjustment our stylesheet. Save those changes and go through the process of adding it to Git. Once that's done, we can push those changes up to our GitHub repository and we'll just check and see that indeed that change has been pushed, which we can see it has. Then if we drop in the DeployBot, we'll see that if we hit the Deploy button again, it will check for recent changes once more and gives us an overview of what it's going to change and deploy. So again, in a matter of just hitting start deployment and DeployBot will push those changes out to our Shopify theme. Now, if we refresh we'll see that that change has indeed taken place. Now, one of the advantages of using a deployment service is that, if we push something that's wrong or we don't like, were able to roll back quite easily and Deploybot as you can see, makes this a pretty straightforward process. We can review again what we're rolling back and instantly pullback changes if something goes wrong. That was the really quick five-minute introduction to deployment which is the final topic for this course. But just before we finish off, we're going to take a look at one final deployment scenario which brings in some more advanced techniques specifically, some of the workflow automation stuff we talked about last lesson. So, we're back looking at the candle store Development theme. But this time around, I have two themes on my store. I have a Live theme and a Development theme. So, we upload indirectly to the Development theme. In Development or using the theme [inaudible] and then we'll be deploying to the Live version of the theme using Deploybot and I've already set up that DeployBot flow in a similar way to what we did with the previous screencast. Now, I've also made some pretty significant changes to the structure of our theme directory as well and that's to fit in with some of the workflow automation stuff that we discussed earlier. So, you can see now that I have a theme directory which contains all of the source files for my theme, and I've also added a Gruntfile which is performing a whole bunch of compilation tasks, so minification and concatenation, and building all of those source files in my theme into a.build directory, here at the top level. To see that in action, let's jump to the console and run a Grunt build, and we'll see that compiles our theme into that.build directory. So, if I open up now, we can say a final version ready for deployment to a Shopify store. Now, notice that the config.yml file is sitting inside this build directory, so that I can run a theme watch in here, and upload my changes in Development directly to the Development version of the theme on the Shopify store. So, if I change directory into the build directory and run theme watch. Then go back to my theme, make a change in the original source files of those themes. So, changing the title of my page for example and then run that build step again using Grunt, we can say Grunt will be smart enough to rebuild only things that need to change and then my theme upload picks up that change and uploads it to the store. Now, if I refresh in our browser, immediately I'm not going to see that change because we're currently viewing the Live version of the store, and we were uploading to the Development version. But we can of course, preview that as we've done here and you can see that that change has indeed been made. Now, we don't want to have to run a Grunt build manually every time we make a change to our theme, but fortunately we also have a watch task setup in our Gruntfile. So, this means that we can now go into our source theme files, make changes as we see fit and then as soon as we save, Grunts going to reap, compile what we need and in turn the theme watch will upload that change to the store. Once we're happy with the changes that we've been making in Development, we want to push those changes up to Git, so that we can deploy them to our Live site. So, to do that, we go through the standard process of Git adding, and I'll change this to a Commit and then pushing that up to our GitHub repository. We can then go through the process of running a Deploy with Deploybot in a similar fashion to what we did in our previous screencast. So, hitting the Deploy button, reviewing the changes that need to be made and then running that deployment. If we go back to our browser and now, we can see that that change has been deployed to the Live site. Let's jump back to our theme files for a second to review what that Gruntfile is actually doing for us and how that works with DeployBot. So, inside our theme source files, you can see that we're not using the standard Shopify directory structure. We've actually broken out our JavaScript and our style sheets into separate files which helps us with Development and keeps everything a little more modular and easy to reason about. In the Build's directory, there are these files are compiled together. What's more in fact, is that if we jump into our Live site in our browser and do a bit of digging into the CSS, there we'll see that the assets that are being served from the Live site are actually not only compiled together, but they're also minified. This is possible because DeployBot supports Build commands. So, if we jump into the settings that are configured for our Shopify theme, We'll see that DeployBot is actually able to run a Grunt build for us before deploying our theme to the Shopify store. You'll also notice that we're passing a production flag to the Build task, and that's to tell Grunt to run some tasks that we wouldn't find useful or too expensive to run in Development. So for example, minifying those style sheets, we'd also use it here to minify our JavaScripts and we'd also use it to minify and optimize our images which is a quite expensive task. It takes a bit of time that we can't really be bothered waiting for in Development, but we'd like to run it before we actually push our theme out to production. Hopefully, you've now got an idea of some good techniques to use to get your code from your Development machine, into a Shopify store in production and avoiding all of those issues that we identified at the start of a lesson.
10. Conclusion: Well, that's it. We are done. Thank you so much for joining me on this course. I really hope it was useful for you, I hope you learned something you didn't know before, and if you feel like you can tackle some more advanced Shopify thing develop now. I'm always very happy to talk to students or anyone in general about Shopify, I spend way too much time thinking and talking about Shopify. So, if you'd like to get in touch or asking questions, give me some feedback. If you get stuck on the projects, then get in touch. My contact details here on the SkillShare course page. Aside from that, I think all that remains is for me to say good luck in your Shopify thing development and happy Kirti.