skip to content

Build a Page Speed 100 E-commerce Site

On e-commerce sites, page performance is everything. In this episode, Håkon Krogh will teach us how to build a web store that aces the Page Speed checks using Remix and Crystallize.

Full Transcript

Click to toggle the visibility of the transcript

Captions provided by White Coat Captioning ( Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.

JASON: Hello, everyone. And welcome to another episode of Learn with Jason. Today on the show, we have Hakon Krogh. How are you?

HAKON: I'm doing fine.

JASON: This is going to be an episode that it really ties into my roots of performance tweaking UIs. But before we start talking about that, let's talk a little bit about you. So for folks who aren't familiar with you and your work, you want to give us a bit of a background?

HAKON: Yeah, cool. My name is Hakon, the head of engineering at Crystallize. I can mention I've been a frontend developer for, well, 12, 15 years or so. It's been a while. I've done my fair share of optimizing for I6, I5 even. Yeah, good days. I started, I started when I remember vividly that when I began my frontend career, we were doing all stuff as you know. We had mutuals in, but it was not a big deal when I started. It became a big deal a few years after.

JASON: Right.

HAKON: And I remember the day I found about about SaaS, I was rejoicing, the CSS provider. I was shouting, calling people over. Come look at this awesome thing. No one understood anything. Just CSS, come on. But it was so much fun. And I've been doing, I've been doing stuff in the very front layer of frontend for a while. Doing a bunch of enterprise e commerce.


HAKON: With their own set of challenges. And doing that for the better part of the last ten years. And I started Crystallize doing more full stack and also open source tooling and stuff like that. Four years ago, and I've been here ever since.

JASON: Yeah. And so, e commerce is something that, you know, I feel like you and I might be the last generation that remembers not having e commerce. I remember when that stuff first started coming online, you could buy stuff over the internet, nobody trusted it, it felt weird and shady to buy something off the internet.


JASON: These days, if I can't buy it online, I'm like, whatever, I'll find a company that will sell it to me online. The whole world has gone online.


JASON: This is something I'm curious about. Especially, since 2020, when we all went indoors. And the whole world had to go online. I saw every company had to immediately figure out what e commerce worked like. And we saw everything from people using things like Etsy, Instagram as the store front and things like Venmo and PayPal and companies going all in on e commerce experiences. As you've been doing this since before the pandemic, so how have you seen e commerce shift even in, let's say especially in the last two years?

HAKON: There has been a shift, definitely. Let's say everyone wants to be online now. We see that. From our perspective, we see a lot more interest from more people. I guess the biggest change is now people really see the value of e commerce. In the past, before prepandemic times, I don't know, the general consensus, maybe you could buy something off the shelves product and that would be fine. You just wanted to have an online presence. But now, it's more about standing out. And transferring that aspect of the physical shop more into the virtual world. If you own a physical shop that's on the street next to your competitors, you're making an effort to stand out, right? Everything from the outside, like, the sound the door makes, the smell you get when you open it, right. The sound, the accessibility, where things are laid out, you know. And everything in that aspect is really critical. It's important to distinguish yourself from your main competitor.

JASON: It's so funny. I didn't realize until very recently that stores commission custom scents. So when you and I knew this about, like, Abercrombie and Fitch, being like, oh, wow, this really smells. But that's like not just an Abercrombie, that's a whole industry is like making a whole store smell branded. Absolutely fascinating. So how are you seeing e commerce stores? So when you go online, you lose that. You don't get the white glove sales experience that you would get if you walked into a high end store. The custom scent or the custom buildout. What are people doing to recreate that feeling of specialness and uniqueness in online stores?

HAKON: Well, most people don't, which is really sad. Because they can. Like, the really ambitious ones, they take full, make full use of the browser. And the environment where the shop is living. So that might be the browser, might be the app. Might be on the smartwatch. That's where we see the biggest shift now. The people with ambitions. The shops that know we're no longer only a store front that's physical on the street, we're actually, we have a presence online. We need to, it needs to feel like us. You know.

JASON: Sure.

HAKON: They need to invest in feeling. Which is tough to sell, right. You can't really estimate how to make a thing, a visual, a virtual thing, make it feel good, right? It's really tricky.

JASON: Yeah.

HAKON: That's a lot of people struggle with that, you know, having to try to put estimates on, I want to make it feel good. How many hours will that take? Right?

JASON: And that's such a hard thing to measure, too. But I know exactly what that, I know exactly what that frustration is because I absolutely have a sense of quality, of solidity and attention to effort and detail that I feel when I use certain apps and websites. I open it and go, dang, this feels great to use. And it is almost identical to something that is a competitor I'll use and go, man, this feels janky, it doesn't feel good to use this. The differences are minuscule but they make a huge, huge difference and I don't know what I would ask for to differentiate when I was talking to a web developer.

HAKON: No, it's a tricky part, I suppose. So a lot of the times to make a website feel nice and smooth and joyful, it's not about having fancy transitions and make things explode everywhere. That's not the kind of thing that would happen in a physical store, would it?

JASON: I I mean, we can hope not.

HAKON: Certainly. It's really about making things smooth and simple, you know. For e commerce, well, you're typically not inviting the user in for a long journey.

JASON: Right.

HAKON: You want to tell them a long story. Maybe you do, maybe you don't. But the point is, you usually the user is your customer. They want to buy something. And if you have that to offer, then you just want to show that's the easiest way to do so. And what most stores do wrong is that they don't tailor that experience in a good way. Sometimes, they're not even in control of the user flow because they're just bought this box here and this box comes from this vendor. It's just a patchwork of things. And they're really in control, right. Well, a very weird trend we've seen over the past is when you enter a site, you know there's going to be at least one, maybe two, maybe three pop up things you have to close, right? Where's the thing I have to close?

JASON: That's true, right? I just kind of allocate the first 10 seconds I'm on an e commerce site to battling the pop ups and cookie flyovers and all of these things.

HAKON: Exactly.

JASON: I have to really want to get a thing to put up with that. You mentioned something I think is really interesting here, you're saying people are reaching for off the shelf solutions. And that creates a bit of a catch where what they're getting is stuff that they don't have full control over. And you can feel this, right? Like, I've used e commerce sites where the main website looks good. And then, the cart is OK. Doesn't quite feel right. And then, you go to check out, and you're very clearly on a third party verified by Visa kind of checkout page and you're like, oh, no. It's one of these, right? And then, there are others where you are like I would say one that's done a good job is Stripe, for example, when you use a Stripe, you're on a third party website but it feels good to use.

HAKON: Mm hmm.

JASON: Where are you finding the right tradeoffs are? I think maybe the biggest thing to establish is, like, almost nobody should take on the burden of building their own payment provider. There are very few reasons where that would be a worthwhile use of time and resources.

HAKON: Mm hmm. Yep.

JASON: But it might be worth building a cart, might be worth building a checkout experience. Where do you draw these tradeoffs? And as you're working, you work with a lot of enterprise e commerce customers, what are the things you encourage them to bring in house for quality versus outsource for, you know, speed and, basically, lack of maintenance overhead?

HAKON: Yeah. So, you know, the ambitious customers that we have, typically, come with a clear desire to reclaim control over the entire experience. And we typically advise them that, well, you should at least have solid control over all of the critical parts, all the path that the user might follow, right? So that's buying something, that's adding the basket, the checkout and what happens afterwards, right? So the user journey doesn't end with you buying it, right? That's the beginning. So you want to keep having that good user communication and flow even after they've completed a purchase. So what we typically do is that we offer people a good template to get started with. But that's something you can completely throw out the window if you want to and do it yourself. So we see some people just using the template, which is, we made some decisions in terms of what we feel is a good tradeoff for most. We also see other ones not using it all. Their own thing they want to do. They believe differently in terms of what works better for target audience. This is one of the things where it depends, but not in the developer pushing off responsibility L for having to actually have an answer, but more that you've got to look at how many developers you have in house. You have to look the a how big of a role this is going to play in your bottom line.

HAKON: Yeah.

JASON: How many dollars you're bringing in your e commerce store. It's going to be offset by typing up these experiences. And it sounds like if we kind of take the 80/20 approach. What's the 20% to get 80% of the results? What I'm hearing you say and tell me if I'm getting this wrong is if you look at the cart and the checkout experience and then think about what happens once somebody has purchased. What do the emails look like? Do they have a clear idea of what they've purchased? What expectations are? When next steps are going to happen so they feel confident their purchase was both successful and they know exactly when they're going to get the thing they bought. If you focus on those things, not necessarily building them out custom, but making sure they feel good. Then you have gotten, that's the 20% of the work that will get you 80% of the results.

HAKON: Yep. Pretty much.

JASON: Now, there's a whole other piece we haven't talked about. And this is the part I think we're really going to be focusing on today, which is the enormous impact that loading speed on an e commerce site has on its conversion rate. And it's just general profitability. There's been a ton of research done on this. And honestly, people are going to spend money on research with the amount of money that's at stake with online retail. You know, Amazon spent a ton of money on this, Google and others have all spent a lot of time and effort on getting research to see what actually impacts whether or not somebody clicks that buy button. And one of the steps I've seen, I think it was from Amazon, was that for every 100 milliseconds you save in loading a page, it translated to a non it was like one percent of increase.

HAKON: It's true.

JASON: And this is where we're going to start talking about the tech. And I saw somebody asking in the chat earlier we were going to talk am I using the right mic, y'all? Let me check and see I'm using the right mic. Let me check. Check y check. Mic. I'm using my Mac pro microphone, I should sound a whole lot better now. Sorry, everybody, I don't know how I changed my default. [ Laughter ] Cool, that's great. I apologize, everyone, for the jankiness of my microphone choices today. Let's talk about performance. And so, we're going to talk about our tech choices here. And today, what we were going to do is work on building an e commerce site and then performance tuning it. The frontend platform. The frontend framework we're going to use and Crystallize as the e commerce. Is it software as a service? Is it a headless e commerce solution? How would you describe it?

HAKON: A headless e commerce tool box, if you would. You don't want to go specific many things, the tool box you need to customize to get you full flexibility and build awesome websites.

JASON: Gotcha. Let's talk about performance, there are a million things that impact performance on a website. Let's start with the basics. How do you give web dev teams the best chance or, you know, again, if we talk about 80/20. What are the biggest things to make initial impact? Where are you checking to see if a page is slow?

HAKON: Server load time.

JASON: That is the, I make a request and how long does it take for the server to get a response back to me?

HAKON: Pretty much.

JASON: And that's going to be impacted by things like your CDN, your how have you distributed this globally. Australia to San Francisco and back or is it hitting a note in Sydney? That one makes sense. Any others that kind of jump out as the initial thing you want people to look at?

HAKON: So, well, there's a bunch of things in terms of load performance that could potentially give you a lot of headache. And after, obviously, server load time, which is many cases, it's going to be solved with by the framework for you. So you wouldn't have to worry about that much. But that's also going to be what goes into that. So is it a pre built static site? Fine. It's just going to be on a CDN. Is it a dynamic one, though? Maybe remix, you have to make sure the services are fast.

JASON: Right.

HAKON: If you're talking to your own database or external service, you need to make sure that's fast. And distributed across the globe, too. Because if you want to depending on if you have a global audience, or not. So the services need to be fast, too.

JASON: Yeah, yeah, for sure. So let's talk a little bit about, you know, you mentioned the frontend framework, how, and here's where we get very just, we're getting heavily into opinion land here. So this isn't like hard and fast guidance, this is just people feeling things. So for you, Hakon, how do you make these choices? What is your what are the heuristics you're using? And what are you reaching for these days if you have to build the frontend and why?

HAKON: Right. And so for the past 3, 4 years I've been reaching for Next.js. It gets the job done well, and it has a wonderful SSR as well as SSG bit. You get the static. Wonderful and you can do dynamic runtimes. Wonderful. It's also keeps being actively worked on and being approved. And as it's non breaking and diversions, you can upgrade to a newer version without much effort and you get performance out of it. It's awesome. But these days, I'm reaching more for remix, the kinds of websites I build. Typically starter kits for e commerce or similar things. Which is, in my opinion, more suited to site work content is rapidly changing, let's say a price changes at midnight. You have to, you have to do to make sure that people get the right price. And you might want to customize sections of the page for specific users, only parts, right. And there's plenty of dynamic things that happen in e commerce that, for instance, don't happen on a blog. Content on a blog usually stays the same for a long time.

JASON: Right.

HAKON: And takes a different framework, not necessarily remix, but that would work, too. The kind of websites I work with, Remix is a wonderful choice and it's also a personal favorite because it stays true to the web natives of things. Which I really like.

JASON: That also, like, kind of what stands out for me. It's most of what I'm doing when I'm using Remix is looking at the NDM docs and not the Remix docs. Which is kind of refreshing after dealing with a lot of frameworks that are very, like, we reinvented every step that you need to just have one that's like, oh, an NDN, it works like that.

HAKON: Yeah, it's important to remember that because frameworks come and go. So if you know the web, you're going to be good. So that's, yeah, and also, I am a JavaScript fanboy. All of my career has been revolving around learning more and doing more with the JavaScript. I do love the fact that you can run Remix without any JavaScript. I just love the fact you can do it. Yeah.

JASON: Yeah. I did an experiment where I just like turned off the scripts tag in Remix just to see how it worked and it worked great. That's so refreshing when you're, like, I don't know, I've turned off JavaScript on other frameworks and it involved a lot. There were config changes, I had to crawl into the output and stuff like that. Mailmain is asking how is that possible? It's possible because of the choices that were made to make Remix SSRs things and uses the platform. So form submissions aren't caught by JavaScript. They are actually form submissions, right? And when you load the scripts, they the page hydrates we progressively enhance instead of shipping all of the functionality into the JavaScript only and then having to kind of back that out to get platform first support. It starts with the platform and sprinkles a little JavaScript on top to make it feel better.

HAKON: Yeah, exactly. We're treating JavaScript as the progressive it has been. Which is wonderful.

JASON: And that's what it was supposed to be. You were supposed to use the web and the JavaScript would make it feel nicer. And I think we got frustrated with the platform. And rightly so. I think what we have to do as a community is look at what's frustrating about building for the web. And use tools to explore solutions to those frustrations. And then, build those tools back into the platform. We saw this with J query, solved a pain query, if you were in the preJ Query world, you may be familiar with the utter nightmare of unifying JavaScript cross browser. J Query gave us nice APIs and they've live in the browser as query selector and a lot of things that didn't exist preJ query, and most of what it was great at is now built into the platform and that is fantastic. That's the best possible outcome. So I'm really happy to see that the JavaScript frameworks pushed the web forward. But we saw a lot of things come in and a lot of the frameworks haven't taken the time to take that step back and say the platform does most of this for us now. Remix did and Remix has the advantage of being a newly built framework and they were able to say what's the state of the world now? Not what's the state of the world in 2015? And how do we kind of work backward? But it feels good to use. It feels like they're taking advantage of the great improvements that have been made at the browser level. And using JavaScript as it's intended to be as a progressive enhancement to improve that experience overall. So Remix for the frontend. Let's talk a little bit about Crystallize and why, I mean, you've been there for four years, right? Obviously, you believe in this product. What is it about Crystallize you feel makes it the right thing to reach for for an e commerce project?

HAKON: It's the right tool to reach for if you have a desire to tailor make something. You want to, if you want to retain control over the user journey all the way through, then you definitely want to pick a headless provider. We're one, there's others, too. But you want to pick one that gives you speed that is it's created in a way that you get all the niceness that you would takes most of your pain away. Maybe that's a better way to phrase it. So in Crystallize, we're this is a platform where we're just, it's a place for you to store your products. And the story that goes with it. So you have the CMS components as part of the product, as well. So you don't have to choose one of those additionally, which many people are doing. So they have an e commerce solution where they have their products and CMS on the side and do you have to semi link it? Build the one thing and then the other? And then try to make that work? So we're one solution for all of that. So we're just essentially trying to do all of the boring and chore parts of the e commerce so you can focus on the really fun part, which is creating those rich UIs and wonderful experiences and we don't want to be in your way, we want to help with tooling and the right kind of asset and resources that you need.

JASON: This is something I've really enjoyed about web development tooling over the last 4 years or so, 5 years or so. We're seeing a huge focus on not on like trying to get people to go all in on a specific way of doing things. Not trying to sell monoliths anymore. We're instead seeing software tools specialize in saying, all right, here's a piece of the web development landscape that hurts. Like, e commerce, in my agency days back in the early 2000s and, like, you know, up until around 2014 or so, if somebody asked me for an e commerce site, I was like no, I don't want to do that. Because it was so much pain and so many things that could go wrong and so many things you have to build in very specific ways or else, you know, and people didn't want to pay for that. Nobody wanted to pay the super high prices for how hard it would be to get an e commerce site right. So you just ended up with these some would pass on the projects. These days, though, between tools like Crystallize and Stripe and Shopify and all of these amazing tools that focus on making this less painful, developers can be off to the races and they do the thing they're good at. I don't have to build a payment transaction flow. I don't have to deal with the security of somebody's private information. That's handled by a company that specializes in that, right? And I just get to put things on the page and build this great experience, which is what I've always been, a web developer. I build UIs and user interactions, I don't build security layer like payment layer software. That's not my specialty. So, OK. So I feel like I could probably talk about this in the abstract for a very long time. But I want to make sure we have a lot of time to code through these examples. So we're going to build a site in Remix with Crystallize and I think the best way we can take next steps is to just let's do it. I'm going to switch us over into paired program mode. Camera 2. First and foremost, let's do a quick shoutout to our captioning, we've got Diane with us today from White Coat Captioning, it is on the home page of the site, Learnwith**Jason.**dev. That is made possible through the generous support of our sponsors, Netlify, making the show more accessible, allowing me to do more fun things like more boop drops and fun things like that. Make sure you go and check them out. We are talking to Hakon. I said your name wrong when we started.

HAKON: No, it's pretty good. Pretty good. Hakon Krogh.

JASON: Go over and give him a follow. We're going to use Remix, using Remix and we're using

HAKON: Yep. So, we're using Remix because I know you did a Learn with **Jason **thing with Remix, I know that's covered.

JASON: Yeah, you can do a command K, give it a search for Remix and we've got an episode with Ryan and Kent. This is a good intro overview. Also, I saw Kent in the chat. What's up, Kent? Thank you for hanging out. We've got the basics of Remix. If you are unfamiliar with Remix, go back and watch one of the episodes, otherwise, we're going to jump in. I assume we're going to spend the majority of the time with Crystallize today.

HAKON: Pretty much. Yeah.

JASON: What are my first steps if I'm looking to build one of these out?

HAKON: All right. So we need to have an idea for shop first, though. What do you want to sell?

JASON: I don't know, I think donuts. I've been thinking a lot about donuts.

HAKON: Yes. I like myself some good donuts, too. Let's make a donut shop. Cool, man. I see you've already opened your terminal and that's probably the first thing people do. If you head over to the website, again, we have a developers thing you can click at the top menu there and you can see, you know, as a bit of intro there. And we do have, sport a little terminal command if you want to start off with a boilerplate. I'm not sure we want to do that today. A boilerplate is cool. It gets you off with a flying start. It includes all the stuff like front page menus, there's cart, there's product and all of that. And checkout and all. We've integrated stuff like Stripe, other providers and all. And so, that's a wonderful thing if you want to get off to a fine start and have it ready in five minutes. I don't think that's what we're doing here today.

JASON: I want to see from zero.

HAKON: Yeah.

JASON: I'm going to create a folder here, this is e comm. So here's our empty, oops. Here's our empty folder, get initialized folder.

HAKON: Perfect. I would start with a bare bones Remix starter.


HAKON: I don't want any bloat. Just blank pages is a good start.

JASON: And so, to do that, we're going to go to this create Remix at latest. And I'm going to set it up right here.

HAKON: It had a way to do, I don't know about styling, we can do some styling in the shop. It's nice to make it look nice, right?

JASON: Yeah, we'll do some bare bones on it. You want me to go with just the basics?

HAKON: Yeah. Just the basics is fine.

JASON: Do you have a preference on type script or JavaScript?

HAKON: Let's go with JavaScript so there's no big typescript things in this. We want to be pragmatic. Agnostic to all frameworks and runtimes whatever.

JASON: Kent is saying we can use tailwind. I actually don't know tailwind, I have barely ever used it.

HAKON: We don't have to.

JASON: I moved ahead before I saw Kent's note and did not. So we are dealing with a perfectly bare bones set up here. So if I do an NPM run dev, we have show up right here. What are you doing? Not found. What did I miss? I wonder if it didn't set up the setup script. Post install, let's try, again. There it is.

HAKON: Nice, nice.

JASON: OK. We've got a very bare bones site.

HAKON: Yes, we do. OK. Cool. Now, we have a running project. I think it's time now to head over to Crystallize and start creating some products. So we can list them out. Yep. Hit the create account button. That should get you started.

JASON: Scaling bananas.

HAKON: Right. So sign up with your favorite provider. And you should be good to go. So now, you are prompted here to do a tenant identifier as well as name.

JASON: Select an option. Test.

HAKON: Is it optional?

JASON: Need to make this a little bit bigger, looks like.

HAKON: Right. Good. That's good. All right. That's it. You're in. So you have what we call a tenant now, typically a shopper in the environment of a shop. And yeah, you have this big create your first product and you can click if you want to. And we can, of course. Do so right now. And you're headed out to the catalog and, yeah, you can give it a name at the top there. And

JASON: Give it a name. So these are going to be our donuts. Chat, what are your favorite donuts? I'm going to start with my favorite donut, which is a buttermilk bar. I don't know if anybody's ever had a buttermilk bar, but ooo, are they good. Long Johns, all right. OK. I'm going to create a buttermilk bar.

HAKON: And we need an image for a buttermilk bar. This is where the story telling begins with a product. Do we have anything?

JASON: Let's see. Look at these beautiful donuts. These are all probably not legal for me to use are they?

HAKON: You can go to Unsplash.

JASON: And I'm probably not going to use actual I'm going to pull like these donut images so I don't get myself into trouble. So let's go back to Crystallize. Go to product story, topics, looks like oh, pick images or drag and drop. So can I just paste?

HAKON: I don't think so. No. I think you need to download first.

JASON: Let me save it. Download, put them in download so I can drag and drop easily. Here is my donut. And there it is.

HAKON: Nice. So what you're seeing right now is the semantics of the product on the top and the product story underneath.

JASON: This is slick, by the way. What a nice little touch this is to throw this image back here.

HAKON: Yeah, yeah. People tend to have really nice images for the products. So this works well. Yeah. Cool. If you see you have zero in stock. We want to have some in stock, though. If you scroll a bit up. You can see on the right hand side of the image, you can change the number there. And we want to have some donuts to sell. Ten of them. And we can give them a price, too, unless you want to give them away for free. There's a transparent, I see now that is odd. There's transparent euro field. You can click.

JASON: Euros is fine. This is a very cosmopolitan chat.

HAKON: Yeah. That's your semantics, that's your product. You've got your name, buttermilk bar, there's a buttermilk dash bar dash and the random number, that's the best guess for an SKU. You probably want something unique. It's fine. The story telling of this product. I'm not sure about donuts. You give it a good description. Keep on doing so on the way down. This is where Crystallize differs from similar providers. You're editing the shape of a product and you can customize that shape if you want to. And add a ton of different different shape components. Right now it's a rich text and collection of paragraphs with images and videos. But you can do a lot more than that, too. And compose, yeah, your sort of shape for the product.

JASON: Gotcha.

HAKON: That's pretty much it. You can publish it now and once you do, you can go ahead and click the, there's a GraphQL button in the top bar. Yeah, there you go. And that's the API.

JASON: So we've already got it and it's going to pull out our nice.

HAKON: This is what you get as a starter, right? Now, you've saved your product and you have this API, you can call and get back structured representation of the product. And for you to use in any way that you want to do. The product Crystallize, the API part at least ends here. The little preview here is data, catalog, ID and all of that stuff, that's kind of the end product that we do.


HAKON: And we want to be fast, so we time ourselves right here, you see the 4 milliseconds up there. That's the time we spent churning on it. Yeah, that's a bit slow, though. We want to speed it up a bit.

JASON: All right.

HAKON: Yeah, and you can see the data there is what we will use for the shop. To create the listings of both, of products.

JASON: I can copy this one and get it up on the page, too. Let's do it the manual way. Buttermilk bar, and I want, I'm going to export const, loader, async and then that's going to be I want to const equals fetch, we're going to fetch from, I need to figure out what that API is. We're going to say method host, body and then I'm going to send in a query and that query is going to be this query that we just copied.

HAKON: Yeah, it's a big one, though.

JASON: I'm going to collapse that so we can see what's going on and I'm going to say variables and my variables were down here, so we can copy these straight in.

HAKON: Mm hmm.

JASON: Now I've got my variables. And do I need to send headers or anything like that? Or is this public data because it's published?

HAKON: It's public data, if you want to. You can get it with headers, but default

JASON: Then, I return the data, and here, I can export default function, we'll call this, I'm going to call it donut because we're going to refactor this. And in here, I want to get data equals use loaded data, that's going to come out of Remix. And then, I'm going to return, we'll just start with donut and then, I'm going to set a pre and need to wrap this all in a fragment because it's React. OK. And then I'm going to JSON stringified data. Let's go null 2. And this theoretically speaking

HAKON: I think you need a JSON string body. I think.

JASON: Here?

HAKON: You don't?

JASON: As long as it's not

HAKON: I think the body is right. But let's find out.

JASON: Let's find out what happens. I'm going to go here, buttermilk bar and oh, only I forgot to put the URL in. How do I find my GraphQL URL?

HAKON: I think it should be part of this page, but it's not, I think your screen is a bit small.

JASON: I'll zoom out a bit, is it in here somewhere?

HAKON: I thought so. So, hmm, I don't remember to be honest. If you just open your network tab, you can see what it calls.

JASON: OK. Network tab. I'm going to run this. And that goes to catalog.

HAKON: There you go. What it does, you get your own name space.

JASON: Nice.

HAKON: Yeah.

JASON: I'm going to put this in here, and now I've got my API, sending it to post, query variables, let's try this, again. And invalidates on JSON body, unexpected token P. That means that something went wrong out here. Unexpected token P.

HAKON: It tries response body. But I'm assuming, I thought you needed to stringify all bodies in the fetch. Maybe I'm wrong.

JASON: Let's see, what comes back here. Let's try this. I'm going to pull this API out and I'm going to go to postman. And we're going to try just the query first to make sure I'm doing it right.

HAKON: You can also just hit that URL. It will give you a GraphQL, you don't have to use postman for this, if you don't want to.

JASON: Wait. What? Oh, like I just go here?

HAKON: Yeah. Yeah.

JASON: Oh, nice. OK. All right. So let me go back and get my query, again.

HAKON: Mm hmm. Yep. It's long. The default, we want to have every possible configuration you might have. And we can make this

JASON: I'll set my query variables. We'll put those in here. And these have to turn into double quotes.

HAKON: Yep. There you go.

JASON: Try, again.

HAKON: Oh, there's comma too much. There's one too many commas in there. I know.

JASON: OK. So that works. And then, we should get back data. So we're sending this and let's logging what we get back here. Let's go back to the top here. So I'm awaiting the fetch, that comes into data. Let's console log what Remix is getting back. OK. And that should put back running the data loader. Invalid JSON response body.

HAKON: Yeah, go back to your URL code. You have an object you pass for the body. I think that needs to be a string.

JASON: You are absolutely right. Yeah. I was looking at the wrong thing when you were saying that needs to be stringified because I was looking at this part. Now I understand. I understand. I see what and now still doesn't work but it doesn't work now because unexpected token P. Wait.

HAKON: Oh, you probably need a content type, as well. In the fetch. Mm hmm. So that should do it, that tells it what it is.

JASON: Hey. All right. Now we have our donut. Next thing I'd like to figure out is how to get this to be automatic. Is it just a dollar sign?

HAKON: Yeah, I think it is.

JASON: And here, I should get RAMs and be able to send in params donut. I can work first try, that would be neat. Let's try it. Ha ha, OK. I love when I do something right the first time. As you've witnessed, that doesn't happen very often. Let's create a new one, then, and somebody said, let's see, I saw some good donut types up here. Kent said Long Johns, I don't know what a Long John is. What's a Long John Doe nut. Google knows my heart. Yeah, I know what these are. I didn't know they were called Long Johns. Let's get this entered in. And so we're going to create. We'll give it 10 in stock, we'll charge two year rows for it. And then, I need to find a picture of one. So we're going to go with the wrong image, but it's going to look great. Let's drop this in here. Beauty. All right. Now we've got one of these. And if I go out here and look, we can see Long Johns, theoretically speaking, if I go Long John, if I can spell it right, we've done it. We have the basics of an e commerce site running here. We're able to to very quickly pull in all of these pieces. And I think you might have flipped your mute there.

HAKON: I did. Sorry about that.

JASON: All right. You're back. Now, we have donuts loading. We have a remix site loading

You hackers, you dirty hackers.

JASON: Ha ha, yes. We have effectively built out a, like, it's I mean, this isn't the prettiest site we've ever built, but this is functional.

HAKON: Functional, yeah.

JASON: Then the next piece is I want to change this home page to be a listing of our donuts.

HAKON: OK, yep.

JASON: How does one in Crystallize get all of the donuts?

HAKON: If you go back to the playground you had on API. Yeah. This one. This is a wonderful start. When you want to get something new. You don't exactly know what or where if I were you, I would delete everything from line 12 and downwards because we don't want that right now. Then, in the query variables, I would change to path and have slash.

JASON: Path is going to be slash?

HAKON: Yeah, because we want a faster route.


HAKON: Delete line 3 to 8. You don't want product right now. And just one more. Yeah, exactly. So we're querying the children, yeah, and we can start with the path for each. There you go.

JASON: Easy peasy. I didn't realize this was going to work, that's much easier than I thought it was going to be. I thought there would be a whole different query. This is great. This is perfect. So let's build this out. I'm going to go to, let me just copy my whole my user data.

HAKON: Yeah, we want to make it easy. We start, the story behind. Why we built Crystallize. And it was out of a passion to build a shop. We wanted just a, you know, for a different company, but we wanted to build a really beautiful looking shop. And we didn't want to mess with the sort of storing products part of the receiving orders part and managing everything like that. And we were looking online for a provider that could do it for us so we could write what you're doing right now. Fetching the products and tailor making those visuals. But there were none that could give us that. We had to make that service, too, while also making the shop. All of Crystallize is made so frontend developers would have a wonderful time pulling data and making awesome stuff, which they're good at. And we should let them.

JASON: OK. We have, I love that. That is excellent. There we go. Getting closer, getting closer. Let's do this. I'm going to actually simplify this a little bit. Let's return data, catalog, children. And I'll just do if it's empty, we'll send back an array so we don't get explosions. And I broke it. How did I break it? Did I spell something wrong? Data catalog. Is it data data?

HAKON: Yeah, yeah.

JASON: It should be result, and let's go with result that data. And there's our donut.

HAKON: Nice.

JASON: Now we get a list of donuts, instead of doing like this, I can do something like a, let's do a ul, we'll loop, yeah, just do the thing I want.

HAKON: This is awesome.

JASON: Beauty. All right. Let's start with that, thank you GitHub co pilot for doing my whole job for me. And we'll bring in the actual link. There it is. And.

HAKON: Oh, man.

JASON: Look at that. OK. So next up, I think, I want to pull images in. So how would I get the image out here? So I'm going to go back to my playground and let's see if I start typing what happens. Nope.

HAKON: Let me stop you before you want to pull image. At this point, some people would be done, though.

JASON: True.

HAKON: Who is your target audience? I have had a couple of previous colleagues that would try to, like, would just browse the web with the text version for a little bit and they would love, if there was an XML or JSON representation because they could just do it an easy parser for that and, yeah. That would be enough for them, right?

JASON: Yeah.

HAKON: So, for some, I mean not many, though, some target audiences, this is actually enough. I have always had a dream of making a renderer that was using Crystallize but a renderer for the old things on televisions, text TVs in those days. 999 pages, you could type and you might not be familiar, no?

JASON: I'm not familiar with that. No.

HAKON: It was before, it was pre web.


HAKON: It was pure text representation. And I used to have a friend who worked in maintaining that. And this is the whole point of this. This is your data, you can do whatever you want to do. If you want images, you can get images, but you don't have to.

JASON: Right, right.

HAKON: Get everything you wanted to get. But I think definitely images in this case. We want to showcase this beautiful, beautiful donuts. So, if you head back to your playground, I'll show you exactly how you can pull that out.


HAKON: Within the catalog, we have concepts of documents and folders and products. So if you want to pull product information, which is this is, you need to do, this is the union type GraphQL, this is going to be awkward for those who haven't dealt with those before. But you have to do three dots on product. And now, you can query the products stuff. And within the products, you have variants. One product is kind of like an umbrella thing for all the different kinds of variants for the donuts. And in this case, it could be the, you know, sizes of this donut. You could have small, medium, large. You could have different flavors within the same kind of product. But we only have one. Yeah. And you could also, instead of variants, you can go default variant. That will give you back the one variant.

JASON: OK. That seems like a good idea. Let's change this to default variant.


JASON: Now, we get an image, the price and how many are in stock.


JASON: OK. Then, using this information, I can go back, drop this in, pretty it up a bit. And then, what I'll be able to do is something like this. We'll say like if donut default variant stock is less than one, then we can return null excuse me for a second. Boy, 'tis the season to just get a little bit sick, isn't it?


JASON: We've got our default variant. We've got if it's out of stock, we'll return null. And then, in here, what I can do is I want to let's just start by getting image out there. I'm going to get an image and the source is going to be, oh, you're doing things for me. And I love it GitHub co pilot. Thank you. Let's go back out here, and see how that works. There's our donuts, all right. So that's, you know, that's not great. But it's not bad. So let's maybe take this and we'll link the image, as well. Maybe down below, we'll do a paragraph tag and say the price is let's see, what's the euro? Euro is remember the alt key for a euro? Oh, no.

HAKON: You can also do used to intl, web API to get the actual.

JASON: Yeah, yeah

HAKON: It's a bit longer, though. You can do stock now.

JASON: Yeah, for this time, we're going to hard code it because we're not going to let's do that and we'll say donut default variant and then, it was default variant price. In euros this goes at the end, right? Whoa. Not sure. Doesn't matter. How did it add a dollar sign? Oh, because I'm in React.

HAKON: Yeah. I get confused, too.

JASON: OK. So then, we can do some super lightweight styling here. Let's get, let's add I think we can just do styles and then, no, how do we do this? We do it by including them in the public folder. Styles. Not there. Here. And then, we create one called we'll call it like AM.CSS and in the root.jsx, we are going to include in the links, if I can find them, export function links and we will return style sheets and will be site main.css. OK, and I think that will be everything we need. Let's double check that by saying we'll take this one and give it a class. And if I take products and we'll make it display flex and then products image and we'll say with, I don't know, 300 pixels, if I did this right, which I didn't, which means I missed something in the link style sheet. That should be right. Oh, no, it's style style sheet because I put it in a folder. OK. OK. Everything is going exactly as planned. Let's try this one more time. There it is.

HAKON: Nice. OK. And this takes me back vanilla CSS alongside kind of what looks like vanilla data pulling, as well.

JASON: Yeah, right we can and this is my favorite way to write style, play along outside like this. You can do some really good oops, I clicked on something. There's that. Oh, boy I keep clicking things. So then we've got that piece and then, I can say products LI and we'll say actually here we want lists style none. And we'll set a margin of zero, padding of zero, products LI, let's actually use the platform. Gap.

HAKON: Yep. Platform.

JASON: That's doing it. That's pretty close. Bump that up a tad. And then, these don't really need much. OK. That's good enough, right?

Yeah, it's good enough. Yeah.

JASON: I wonder if I do a hype, 300 pix and what is it? It is object fit. We'll do center. All right. I did it wrong. Cover.

HAKON: It's contain or cover.

JASON: All right, we have conquered CSS.

HAKON: This used to be a pain in the past, though. This is so tough to get right. And now

JASON: It was a nightmare to get right. Yeah.

HAKON: Yeah. Oh, man.

JASON: Now, we can do kind of the same thing here with can you scope the CSS for that file specifically? Yes, you can. Where I'm importing this links, I can put this on the index file only. It would show up there. My thinking here is that we're going to have so few styles I'm going to throw them into one thing. But yeah, we could absolutely do it where the main would show up on the index page and I could have a product one for each of the donut pages and things like that. But yeah. Let's see. This is the Microsoft Edge thing, don't worry about that. I don't know what that is.

HAKON: Yeah.

JASON: Now, we've got that, I can set the same thing up with my, let's see, I'm time checking, we've got 25 minutes here. I want to do a lightweight version of the same thing here so I'm going to. We're going to rename this one to result and then, we're going to return data, and it was catalog.

HAKON: That's it. And that's got to be yeah, object. Yep.

JASON: Now, we have our basic object and we can do one of these. So we'll send the let's call this donut. And we'll say Is that right? And then down here, we're going to need a little more data because I need to show the image and then, we're going to need to show purchase details. So to do that, can I do the same thing that I did over here where I, if I set this to buttermilk bar


JASON: And run the same query.

HAKON: It's going to have no children, of course, but if we remove that part, that's going to be

JASON: OK. Great. I'm going to take this. Let's drop it back in.

HAKON: Yeah, this is going to clean this up a bit, too.

JASON: Yeah, not quite so intense of a query right out of the gate. Why don't I get this image here and we'll drop that in and that should just work, it does. And then, I can get the purchase details which for now are going to be this bit.

HAKON: Yeah, fine.

JASON: And we're going to need a button that will say, are we going to add to cart or buy now given we have about 20 minutes?

HAKON: I think we want to do more performance than buying stuff today.

JASON: All right. We'll just we'll start there, right? That's kind of the basic thing and then, in my main.css, I'm going to give this a class name of product image and then, I can exist and say products image as well as product image. Yeah. Good enough, right?

HAKON: Good enough.

JASON: Pretty basic setup and we'll give ourselves one more bit that we need, which is a link to, I need that to be in a paragraph so that it's not on the same line. We have a fully navigable e commerce site now.

HAKON: Yeah, we do.

JASON: That's slick for what we've been working on this for 30 ish minutes now? 35 or so? That is not bad.

HAKON: No, no, not bad at all. That's nicely done with the CSS, as well.

JASON: What's the next thing we want to do here? Do I want to run a test on this straight up?

HAKON: Yeah, how you can perform and really tailor nicely. So do in the browser, I'm assuming plugins might affect the score.

JASON: We'll see how it goes. I can pop it open incognito window if we see changes. I did something with accessibility, my alt attributes are empty because I didn't set them. Links did not have a discernible name. Oh, and they don't have alt text, right? I can fix that very easily, what about SEO, I don't care about that just yet. This is all pretty good. This part, I'm not 100% sure what caused it here.

HAKON: You're getting penalties for text compression because it's local host.

JASON: Oh, should I deploy this, then?

HAKON: Let's try that, yeah.

JASON: If I had more time, I would do it, I would do it by actually deploying and setting up the CI/CD. I think it works. I don't want to take that risk right now. Ecomm remix Crystallized. So then, once we have that, you can go down to the deployment so I can NPM run build. Then, I can deploy prog, I'll drop that right in.

HAKON: Straight to product. Exactly like we want it. This is how we do it.

JASON: This is how we roll, straight to prod. And we are almost done here, just a few more seconds. Off it goes. There we go. There we go. There we go. And live. So there's our site. So now, if I run it, again, we're on desktop, try one more time and see what we get. OK, deployed with page compression and everything, 100 right out of the gate. Now, everybody, I know you're looking at this going, but there's nothing on this page. I know. And that's kind of by that's kind of by design, though, the perfect e commerce site is the one that lets you see a product and buy a product. But obviously when this hits reality, that's not going to be the case. I'm also curious, what do you think this is going to do on mobile? What are you waiting on, Mickey? There was nothing to hold on.

HAKON: Yeah. Mobile is always tougher, right? There's a lot more considerations to do. We're getting total blocking time penalties, which I don't really get because what do we have here that can block?

JASON: That's got to be, let's look at the network tab and disable cache, try this, again. Our blocking time looks like initial request, everything is rolling here. I don't know, it's all pretty fast.

HAKON: In any case, the framework would add some things on top that made the, made the client work a bit more than maybe what is ideal. I think that was a thing, though, from the remixing samples I've seen. The blocking time is almost zero.

JASON: Who knows, the thing that is challenging with these is they don't run in isolation. And so is it going to be exactly the same this time? It's exactly the same.

HAKON: Cool. OK. Fair enough.

JASON: I don't think I have any plugins, but we'll try.

HAKON: Yeah.

JASON: That is true if you test in incognito. Yes, that was the problem, I must have an extension on and now we have zero blocking time. So that's a mobile test.

HAKON: That's a mobile test, yeah.

JASON: So our brand new e commerce site. And here's maybe the big important thing to call out, chat, you're all going to say this is a this is just a bare bones site, there's nothing on this. Yeah. Try this same exercise with other frameworks and I don't know that you'll get the same results. And that's kind of what's exciting here is that we got set up for success from the beginning. Now, we will get asked to do things that will make this slower. Like a Google tag manager or, you know, these sorts of tracking scripts that we need to add and that sort of stuff. But we're starting from a point of very high performance here.

HAKON: Yes, we are, and obviously, this is two products. And given the time we have left, I don't think we have can do a whole O lot of performance optimizations. But I want to show you a little trick that a lot of people are going to like. The first thing that's going to happen here is you're going to have a lot more products for sure. You want to have more than two donuts.

JASON: Sure.

HAKON: If you have a hundred of them or more, or embedded videos or something cool. Then, you're going to have challenges with your speed. The images being downloaded are your original ones you pulled down from Unsplash, they're probably big.

JASON: Yeah, we can probably see by Inspect, where is my Inspect button? Down at the bottom where it always is. Yeah, we can see here, I'm showing it at 300 by 300, intrinsic size is 800 by 1200. And it's, you know, it's 25 kilo bytes. Doesn't need to be that big. Lots of things we can do to optimize this.

HAKON: 25 isn't that bad, though.

JASON: Too big for a 300 by 300Jpeg.

HAKON: If you go back to the playground, I can show you more of the things we do under the hood. Here for first image is URL and alt text. If you add a new line, you see you also have other fields available. Go down to variants. This is the variants generated for each image you upload.


HAKON: URL and with height maybe size. And here we go.

JASON: Key is not interesting, I'll drop that one. OK. So this is interesting. We've got all of these different sizes. 200 by 300, 200 by 300. Cool. Very cool.

HAKON: OK. If you're on a framework or in an environment where you kind of have to serve the images directly from the API, this is one of the things we build out. We know that this is painful for developers. Writing their own down scaling for images and all of that. So for every image you upload, we're going to generate web Ps and the original for you, put them on the CDN and have them ready for you so you can do whatever you want to do with them.

JASON: That is really handy. So you could do something to build out a source set. Have the fall back so it would try and fall back to a web P and fall back to a Jpeg and the best possible outcome. The web P in this case is smaller, which is surprising. But you can also see, these are teeny tiny compared to that 25 kilobyte we're serving. Here's 9, that's much better than what we were doing before.

HAKON: Yep. Exactly. So pick the one that you feel is best for your user base. And typically, you want to have them all in a source set. We know that this is painful by hand which is why we built it into the platform. It's there for you.

JASON: And this is one of the things that's not shareable code. Do you know are people building these in the wild that will turn one of these results into a source set for you?

HAKON: We built one. Crystallize@npm React image, you get the full picture tag with source sets and all of that.

JASON: Really nice. Cool. So this will be one that will really cut down on page load times. This is a third of the size of the original image, maybe a little bit bigger. That's immediately when you start talking about lots of pages is going to make an enormous difference in how these pages load. What else should people be paying attention to?

HAKON: Actually, the actual query you write. We dropped the default and wrote our own.


HAKON: Exactly the data that we want toe show. This is also a place where you can save a lot of, well, I'm assuming blocking time as well as sort of pay load for the page. The more data you pull down, the more user has a download, too. If you can tailor make those queries, make them as tiny and condense as possible, you're going to make it easier for yourself. Also

JASON: There are a lot of ways you can handle this. In Remix, we are pulling out the piece that we need and so we could fetch everything. If it was a REST API, we would fetch everything and then map over it to pull out just the details that we need and return that modified object. But the nice thing about GraphQL is you just don't send the details you don't need. Like, don't even ask for extra stuff. If I need the URL and alt, cool, ask for that. I'm not asking for a ton of additional details here because as we saw when I look in here, there are tons of things I could be getting. But for this particular site, I don't need them, so don't ask for them.

HAKON: Exactly. Yep.

JASON: That makes sense.


JASON: Any other pieces people should be focused on?

HAKON: Oh, there's, in terms of web performance, there's a whole bunch of things that can go wrong. But I'd say we're all about the tailor making and we just love that people take full control over their frontends. So that's probably the most important thing I want to mention is we have a starter here now. It's a hundred page speed right now. Set up the CI now, make sure

JASON: We could do that. For example, there is where is the build plugin? Netlify, Lighthouse, this is an older post, but what's cool about this, this will run Lighthouse on every deploy and set thresholds if performance drops below a certain amount, it'll fail. You can set your site up. Don't take a build live if the performance drops below 90.

HAKON: Exactly, yeah. This is awesome. If you start off with 100 or 90 or something really, really good and you add this, then you're just going to be bugged every time you drop below.

JASON: It's really, really nice. I love that it's all and you were talking earlier, the goal of Crystallize is to take a bunch of things that are usually going to run the same but are just labor. It's not fun, it's not unique, doesn't really add value, it just needs to exist and needs to be done well, right?


JASON: Crystallize will give you those pieces that you need for your business to run well on the e commerce side, the e commerce tool kit, and then, you can rely on in this case we're using Netlify and the plugins to give you exactly the same thing but for your CI/CD. Get the e commerce tool kit, now get your site building every time you push to get, fail to build if the performance drops below threshold, that'll alert you in Slack or in the GitHub PR to say like, hey, something happened that hurt performance in the site. And all of those things are things that just take manual QA, manual labor off the table and let you focus on building features and building things that differentiate your business, not just that table stakes stuff that lets you operate.

HAKON: Exactly, spot on.

JASON: Very, very cool stuff going on here. So Hakon, that's pretty much all we have time for today. What should people do if they want to take this further? If they want next steps and want to go deeper down this rabbit hole?

HAKON: Cool. Check out our website. We have a lot of boilerplates, too. So if you want to try Remix, completely built Remix site, there's one for that and there's, we do livestreams every week where we do one topic from all from sales marketing to very deep tech stuff. And we have a Crystallize community channel on Slack that you could check out. And everyone's from Crystallize is in there and answering to all kinds of questions on how to build really awesome stuff. So yeah. That's where I would start. Usually that our website is a gateway to all of those resources.

JASON: Great. if you want to go in deeper, check out this developer's tab. Make sure you go and give Hakon a follow on Twitter. And let's do one more shout out to the captioning we've had Diane with us all day from White Coat Captioning, that you think, Diane, for being here, that is made possible through the support of our sponsors Netlify, NX and Backlight all kicking to make the show more accessible and more fun in general. While you're checking out things on the site, make sure you take a look at the schedule, we've got a whole bunch of fun stuff coming up today. Later this week, we're going to look into commandbar, when you hit command K and a bunch of fun stuff opens uh. Now commandbar is a company that specializes in building these. I'm pretty excited to see how it works we've got one on the Netlify site I love. And we're going to get into more fun stuff, we're going to get into TRPC and Type safe APIs, a build plugin with Chance from the Remix team. And we'll be doing more. I have a bunch of stuff I haven't added to the schedule yet. Aiden has been in the chat reminding me I need to do that. Sorry, Aiden, I'll get to that. This was so much fun, I am really glad we got that 100 page score on desktop and mobile. I was a little nervous when it was showing me 88. Oh, no, did I screw this up for everyone? But this was great. Hakon, any final thoughts or words for anybody before we call this done?

HAKON: Do things the web way, the fast way. And I'm going to be having a wonderful time looking at your sites that you make. Just do it fast.

JASON: All right, y'all. That is going to be it for us today. Stay tuned, chat, we are going to go find somebody to raid. Hakon thank you so much for spending time with us today. We will see you all next time.

Closed captioning and more are made possible by our sponsors: