Vincit Dev Talks is a quarterly tech meetup held in Southern California. It’s designed to bring directors down from their towers and developers out from their cubicles. We feature speeches on a variety of topics ranging from marketing and business development to software engineering and design. Talks will be brief, but informative. Check out vincitdevtalks.com for upcoming events.
In this talk from our May 2020 event, Lead Designer Cameron Sagey and Senior Developer Viet Le from Vincit discuss strategies and decisions made during the design and launch of Urban Armor Gear's completely revamped website. Cameron discusses his motivation behind various design and UX decisions, while Viet describes how and why his team used Gatsby, Shopify Plus and a headless CMS to implement the designs and deliver a lightning fast user experience.
Cameron: I'm Cameron. I'm Head of Design at Vincit, and me and Viet were on the UAG project. So, we figured we would go through the process, some of the decisions we made, and some of the more interesting aspects of it.
Cameron: So, I'll just jump into UAG as a company. They're a global device case brand. So, iPhones, AirPods and so on. They've got a really interesting brand. It's really rugged, almost military style, and so the design language matches that.
Cameron: The problem was, they had an existing website, but they had optimized it a lot. But, they'd reached the limits of their current site. Their A/B testing wasn't producing results anymore, so on. They also had a need to spin up new pages and customize pages, because of that interesting brand, and it wasn't working for them. So, some of the goals were customization, performance, usability, and brand expression.
Cameron: So, some of the things we thought about in the approach we took, we needed to find a balance between the storytelling and shopping, because sometimes an awesome brand doesn't lend itself to usability and whatnot. That was one key aspect. UAG has an awesome design team so we wanted to highlight their work instead of detract from it. We definitely wanted to focus on a solid mobile experience. Then, we made some interesting depth decisions that Viet can mention real quick.
Viet: Hey guys. For this project, we wanted to go headless commerce. Headless just means separating your front-end from your back-end and having the two interact through APIs. This allowed us to build the site statically with Gatsby, hosted on a CDN like Netlify, pull pricing and availability from Shopify, while getting everything else from Contentful.
Viet: Site speed was also something that we wanted to improve. Some of their Shopify collection pages were slow to load, sometimes taking up to three to five seconds. For me, personally, if a site takes that long to load, I'm probably not going to stick around. Because we wanted to improve site speed, we decided to go with Gatsby. Everyone knows what React is, so I'll skip over that. Gatsby is a static site generator that I'll talk about a bit later. Gatsby sites are built using React. And, on top of that, they are known to be really fast.
Viet: Reusable components and templates came up a lot during the planning phase. The client wanted to be able to control the layout for the landing pages and the content pages. Drag and drop, rearrangable, reusable, those are a few of the words that came up. So, when it came to development, we kept composability in mind and I'll show an example of that later too.
Cameron: So, taking a high level look at the process, I guess you could split it up into three main phases. So, this is planning, building and improving. So, the planning is super important and that's actually where you can sometimes provide the most value as an agency is... so, it's in the user research, business goals, planning your backlogs and prioritizing everything. So, that's super important. That happens first because you want to take a big picture look at the project before jumping into focus sprint. But, once you get into the build phase, that's when the Agile workflow starts kicking in. So you're designing, implementing, and testing. Then, we launched the project. And, this is where we currently are, is testing, improving, and then repeating.
Cameron: So, I'll jump into some of the steps in the design portion. So, first, we start with Discovery. So, this is part of that planning phase. What we're looking at here is, goals, users, features, and anything else that the project calls for. Mainly we're learning and planning here.
Cameron: So, one of the most important parts of that is user research. So, you always hear the term user personas. There are multiple other ways of doing user research. So, one of the interesting things we did here is we tried to remove all the fluff, because user personas have a lot of good data and you want to stick to real data as much as possible, but often there's a lot of assumptions built in and so on.
Cameron: So, we tried to remove as much of that as possible, separated out the hard data and then combined user journeys into the personas. So, I don't know if other people do it this way, but I highly recommend because you get a look at the flow a user will take through the product. So, it ends up being more useful.
Cameron: The general purpose of user personas and user research is to make user's stakeholders. So, it's not just about the business goals or the stakeholder opinions within the company, you should really be looking at users and what they need.
Cameron: So, we take those, throw them up on a wall, when we have a real office to work with, and brainstorm with the client, and, basically, just throw out post-its up on the wall, map them to which persona they relate to. So, we're thinking of it... It's creating a user-centric process where the client is forced to think about which user he's creating this feature for when he adds a feature.
Cameron: From there, we've got a ton of features, both current features and future features, and we map them out according to the value they provide the users and also the cost it takes to implement. So, from there, we use a tool called a red route to do that, but you can do it multiple ways. But from there, you have a nice prioritized backlog. So, it's a good starting point for the project.
Cameron: So, out of those features, it's all kind of, everything's there. We want to structure it and organize the content. So, we'll do some card sorting and build a site map. So this is building the IA, Information Architecture. It's pretty basic stuff, but I think one interesting method for this that I found works well is, if you choose a criteria to organize the content and then stick to it. So, if you organize your content by content type, that would work, whether it's videos and images, or if it's by use case... so it's shopping and exploring. That usually it keeps it consistent.
Cameron: So, once we've got everything mapped out, we jump into wires. We do it a bit differently than you might have seen from other agencies or designers. We try to minimize this as much as possible. We're not thinking about layout. We see this as a communication tool. It's a lot easier for us to communicate concepts when there's a visual document to look at. Then, internally, the main use for wireframes is working on the flows. So, we definitely want to prototype this, click around, make sure that the flows are working well.
Cameron: Also, you'll notice that it's blue. That's just a little trick that we use to make it more easily understood that this is not design. This is a blueprint.
Cameron: So, now we're jumping into the design phase of things. But, this is sort of, a middle step; it's still planning-ish, where we're working on the creative direction and setting the main themes. We want to do this before really jumping into Agile sprints, because we want that overarching theme to make things consistent and make sure anything we build in the sprints is not going to have to be reworked.
Cameron: So, I think the main thing to mention here is, we create those themes based off of everything that we've learned in the discovery. It's an ongoing process. Then, an interesting thing for UAG... So, I mentioned the usability versus brand expression. So, we actually created two example styles during the creative direction. What you see here is the shopping style. So, this is focusing on usability. It's trying to keep things very simple and easy to use. Then, we have the other style, which is the brand style, and this is used for their content, for their blog pages and media and everything.
Cameron: So, what we can do is between these two styles, you've got your product page and your blog article. Well, in between those is the homepage and the blog list page. So, we can blend these styles. So, as you navigate the site from a shopping page to explore, or vice versa, the design transforms as you navigate.
Cameron: So, now it's UI Design. We've done a lot of work up and to this point, but actually UI design is the bulk of the hours spent. That's because we've minimized wireframes. We're thinking about layout in the UI design itself. It's not just coloring in or anything. We do a bit of work on the flows as well here. Because you can actually see the hierarchy, once things start to come to shape and that might influence flows or layout.
Cameron: One thing we really want to do here is build everything with components and styles. That's, A, it's more efficient working that way, but also that's how it will be built. So, if you build it that way in design, it's going to be a much smoother handoff. We also prototype again here. So, it's a much more fleshed out prototype. This is going to be the source of truth for the designs. Here you can see some of the finished screens and then we'll talk about development.
Viet: All right. Kyle [crosstalk 00:11:03], let's go into the next slide.
Viet: So, Architecture. The storefront is built using React TypeScript styled components. Data is queried using GraphQL and components were built with the help of storybook. All of the business logic like, inventory and pricing lives in Shopify. Everything else lives in Contentful, including product information, images, assets, contents, and branding. Changes in Contentful will trigger a Netlify build during the build phase. Data is pulled from Contentful. Landing pages, product detail, pages and collection pages are all generated based off of Contentful data. Collection pages are generated using different combinations of product fields. For instance, we generate collection pages like collection/iPhone 11, collection/Apple phones and collection/sampling phones.
Viet: When a customer lands on a collection page or a product page, prices and availability are fetched dynamically. Reviews are fetched using a Netlify Lambda function. Carts are created and mutated using GraphQL and the Shopify storefront API. Finally, when users are ready to check out, we send them over to Shopify's checkout.
Viet: Next slide. So, an overview of Gatsby. Gatsby is a static site generator. You can pull data from a source of your choice. In our case, we used Contentful, but Gatsby supports a wide range of data sources. We've also used it with DatoCMS and Netlify CMS, for instance.
Viet: When developing, you're using React and modern libraries. Pages are static initially, but unload, they behave just like normal React apps. This means you can use state hooks and any other API available in React. Since Gatsby builds your site as static files, you don't need a back-end. You can deploy it over a CDN giving you efficient caching, fast delivery, and reliable availability.
Viet: Next slide. Gatsby Bootstrap Lifecycle. Gatsby does a lot of stuff under the hood. I've included a link to a pretty good breakdown of the Gatsby Bootstrap Lifecycle that I encourage everyone or anyone who is interested in working with Gatsby to take a look.
Viet: But, in summary, during the build phase, Gatsby will source and transform nodes. Build out your schema, create your pages, extract your queries, and run your queries. And, finally, write out your page data.
Viet: Next slide. Contentful. Contentful is a headless CMS. Your content is organized in two spaces. Each space has a content model and content models are made up of content types. This is where you define how your data is going to be stored. We use content types three ways.
Viet: First, we use them as entities. For instance, we have products, product variants, like different colors, brands, devices, etc. These are all entities and entities can have one-to-one or one-to-many relationships. Each product can have one brand and each brand can have many devices and so on.
Viet: Second, we use them as components. We map some of the bigger components to content types. I'll show you guys an example of this later, but for now, this ties in pretty nicely with the last point. Like I said earlier, composability was something that came up in the planning phase.
Viet: The client wanted to be able to drag and drop and rearrange components. We also wanted them to be able to generate standalone or promotional pages using available components without needing to ask a developer.
Viet: So, lastly, we also use content types as views. To the right, I have an entry that uses our page content type. This content type is used as a view. Our page content type has a field named content that accepts entries that use content types that we have mapped to React components in our library. I'll show you how we do that in just a bit, but this gives the client the ability to create new pages, using any component available in our library. They can create new entries or even reuse entries from another page. For example, they already have a product list that showcases Samsung phones. They can insert that same entry into this page without having to create another entry. So, putting it all together, I wanted to show some quick code examples of how we generate pages and how we map React components to entries using Contentful.
Viet: So, the next slide. So, the first part, Generating Pages. There's three ways to create pages with Gatsby. We use the create pages API provided by Gatsby. This API is used in the Gatsby node file. Code in this file is run during the build phase and create pages is called after the sourcing and transformation of nodes and the creation of the GraphQL schema. Meaning, you can query your data from your data source and then create pages based on your results.
Viet: Starting from the top, we're using the create pages API, and we're basically running a query for all of our products or Contentful entries that use the product content type and all of our pages or content entries that use the page content type. Then, we create pages based on the results. I've left some code out, but page nodes, unique devices and product nodes are arrays. They are the result of transforming and formatting the data that we got back from running our query.
Viet: To create pages, we iterate over each array, calling create page on each iteration. Create page, takes three parameters, but we're only interested in the first one and I've destructured it here. Path is a valid URL and must start with a forward slash. Component is the absolute path to the component or the template for this page. Context is any contextual data that we want to pass through the component either as a prop or made available to the component to use as a variable in a GraphQL query.
Viet: Next slide. Honestly, I tried, but there was no way to make this slide look pretty. There's a lot going on so I'm going to give it a brief overview. These have been modified slightly just to serve as examples. So, let's start with the bottom-left. This is basically the React component that gets rendered for a page. We have a layout component that wraps our SEO component and a component called Contentful content, which is the component that's going to map Contentful entries to react components.
Viet: The bottom slide in the middle is the template file that is loaded in Gatsby node, which you saw in a previous slide. In the query constant, the variable page slug is getting passed in through page context. We use this variable to get the entry for this page in Contentful. The fragment page data fields contains all of the fields that we want to get for that entry. As an example, I've included the fragment for our Contentful image grid fields at the top-middle, but you can assume the missing fragments all look similar. This query is run and the results are passed into the page component on the bottom-left as data.
Viet: Finally, on the right, we have the Contentful content component. Here, we are basically importing components and mapping them to Contentful entries using the typeName field. This field is provided by Contentful for every entry and represents the content type for that entry. For example, if you had a content type called page, the typeName for all entries of that content type would be Contentful page. We are also recursively rendering components in the case that a component is made up of other components.
Viet: So, putting it all together, almost nothing is hard-coded. Our collection pages and our product detail pages are all generated programmatically while all of our other pages can be fully customized on Contentful to use available components in our component library. This allows the client to quickly throw up limited promotion pages, composed of new components and/or reused components.
Viet: Say, I have an upcoming product line that I want to promote, or maybe I'm running a promotion that's relevant to the times, so I log into Contentful and I create a new entry using the page content type. I pull in a media carousel that we are already using on a different page and I'll add a couple of new entries, maybe an image grid component, a highlight card component, maybe a product slider component, add some pictures, write some words, and then save my new page. This triggers a Netlify build on my staging site. Once that's done, I can check it out. If I'm happy with it, I can go back to Contentful and I can publish my new page. This triggers a production build and in a few minutes, my promotional landing page is live and I didn't have to write any code. That's it for me. So, I think I'll hand it back to Cameron.
Cameron: So, now we can answer any questions that have popped up, but I'll need somebody to read me them.
Rachel: Yeah. The first question that came was, why did you choose Gatsby over another SSR?
Viet: To be honest, it was new and shiny, and it was fun to work with. We had previously come off of another project that we used it on, and it was extremely easy to use, easy to pick up and learn, and just fun to work with.
Rachel: Another question was, why couldn't Shopify handle the page customization by itself? Why the need for extra components?
Viet: I would say that we wanted to get away from working with liquid templates. We wanted more control and more customization when it comes to what components we're putting out. Moving away from Shopify meant that we could work with React and modern libraries. I see, in chat, Michael's from UAG... and speed, we wanted more speed too.
Rachel: Great. Well, I appreciate you both. Oh, last question was, how long did the project take from start to production?
Viet: Overall time. We launched the site beginning of January. I forget what month we started. I think Cameron would have a better idea since design started first.
Cameron: Yeah. I don't have a good answer, but my my guess is, probably, about six months, maybe.
Viet: Six months.
Rachel: How long is the build time now?
Viet: The site builds in around five minutes right now. Keep in mind, this is also a few hundred pages too. We're building out all the collection pages. Okay, and all the product detail pages as well. I would say that during the build phase, the part that takes up the most time is getting data from Contentful. The actual building out of the pages doesn't take that long.
Rachel: Great. Well, thank you guys both. Just being mindful of time, I think we'll wrap things up there.