skip to content
Home

Custom Discount Codes With Fauna, Tito, and Shopify

with Rob Sutter

As part of Jamstack Conf, Jason is building a swag app with experts from around the community. This 5-part series will go through the whole process of building an e-commerce site with Shopify, Algolia, Sentry, Twilio, and Fauna.

Transcript

Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). 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: Welcome back, everyone. We are ready for, we're ready to go. We're so excited about this. I have the wrong thing going. What's going on here?

ROB: Hi, everybody, I'm Kelly Vaughn. That's cool, you gave me instant intelligence upgrade there. Sorry, Kelly.

JASON: Kelly is brilliant, but why aren't you updating? You're supposed to update.

ROB: I'm not mad.

JASON: Just, everybody, please pretend this is Rob Sutter and hopefully, that will update at some point as we move forward. Man, I changed everything. I was so careful.

ROB: I'm going to fix this the old fashioned way. Watch this. Here you go. We don't have a lot of time. Keep going.

JASON: So. We've brought in Rob because what we need to happen next is now that we've got the cart running, which by the way, you can go and play with now. I deployed it while we were in the break. So you can go add things to your cart and all of those good things. Nicely done. Yes. Not Kelly Vaughn. I love it.

ROB: Sometimes, the simplest solutions are the best.

JASON: So good. Yeah. But we've got I'm going to try this refresh one more time. It was supposed to time out after do it. Do it. Oh betrayed. Betrayed. OK. I set it to time out and I just, you know, I don't know. I don't know what to do. Holy crap, I saw that Chris Bicardi has been subscribed to my channel for 28 months. I didn't know I'd been streaming for 28 months. Thank you, Chris, that is wonderful.

ROB: There from the beginning.

JASON: Yeah, Chris has been down from day one. I think he and I started streaming at about the same time. And he's moved on to mostly streaming through other services, here I am, still Twtiching.

ROB: Here we are.

JASON: First of all, quickly, can we get an introduction to you. Like, what's your story? What are you about?

ROB: My name is not Kelly Vaughn, my name is Rob Sutter, head of DA here at Fauna, Fauna's the data API for modern applications. Which means, you know, think of it like a database that you access like an API, perfect for the Jamstack. The same way that we're accessing all of our data today in Shopify for e commerce. Put your data about your users, your items, et cetera, into Fauna, as well. And off you go. I've been a serverless builder for a long time. I am awful at frontend. I'm here to support your database backend endeavors in any way I can. And thank you, everyone, for joining us today to listen to not Kelly Vaughn talk about databases.

JASON: Absolutely. And also, as we're switching over, let me do a quick shoutout. I'm going to jump into this so we don't run out of time. So first and foremost, I deployed the app if anybody wants to see it, you can go and look at this. I'll be deploying to this branch, deploy preview throughout the day. So that as we go, you can kind of see things as they go. There's this pull request here where you can see what we're doing and like what changes were made. If you want to review this, there is a much, much better setup here we can use. So, yeah, now you can kind of follow along, and what we're going to be doing in this particular session is we're going to use Fauna, which is a database, and we're going to use serverless functions. FYI/functions. Look at that short link. I love it. Let me drop this in here so you can all see. And, we're going to combine those things to use the tito API. This is Tito, a ticket service, that's what we used for the Jamstack Conf tickets. And then, we're going to combine that with Shopify's coupon codes. We're going to create coupon codes using Shopify and hook those up for registered people so that when you come and look at this, you can get a coupon code that will let you get some of this swag for free. Like this slap bracelet stay tuned, once we get this running, you'll be able to claim one of these slap bracelets and get it for free.

ROB: It would be a shame to put my information on top of everyone else's. I'm kidding, we can't do that.

JASON: Yeah, we have a limited quantity of these. Make sure you order them. I just said backend, we're not going to use a server to do this. We're going to rely on serverless function and to explain it, it feels very complex. Let's look at this code, I wrote this out as a to do. I have some of this stuff preceded so we don't have to write it out ourselves here. This is a call to Tito's API to let us get somebody's ticket registration by their email and includes the secret key to make that call. We check that, pull back the registration. We have the ability to send a Shopify request. Which goes to the Admin API and gives us the ability to load out their data from the Admin API. We have the ability to load or create a Shopify customer which we do THU this mutation here. And then, we get that customer if the customer exists, we will load that customer and then, send back email and otherwise, we'll update that customer with a tag. The tags are how we're allowing people to claim the slap bracelet is by kind of tagging them there. I didn't want to make us sit through all of that. We don't have time. Send a request to Fauna, we need to create a claim for one of the coupon codes and load that claim by email. If you are a holder of such a claim. Here's what we're going to do. This is where it starts to sound intimidating. Here's the logic we're going to run. First, we're going to check Fauna for an existing claim. If you already claimed a discount code? And we're going to get the total claim count. There's an upper limit on this. Only 1,000 of these things were made. So we have to make sure that we don't have give away more than we actually have to give away. Then, if a claim exists, we're going to return that discount code. We stop here. Here's your discount code. If a thousand claims had been made, hey, there's no more left. You can't use them. If not, we're going to check the email against Tito and make you have a valid Jamstack Conf registration. You have to register if you were registered, then you're in the database, you just have to use the same email you used with Jamstack Conf registration. If not registration exists, sorry, but you can't claim a slap bracelet. You've got attend to get the perks, right? And then, if we get a valid registration, associate with a Shopify discount code which allows you to claim the bracelet for free and we will then store that claim in Fauna so that if somebody runs this, again, we get here and run back. We don't want to do too much work if we don't have to. This is hairy amount of work to do in less than an hour. We're not joking around here, we've got a lot to do. But, yeah. It's a lot.

ROB: Let's get after it. I've got good news for you.

JASON: I'm ready. I want news.

ROB: The very first one you had up top, can you go up to the top, again, the first to do that you had? Send Fauna request. Hey, I remember from the last time we streamed together, rhetorical question, how do you feel about GraphQL?

JASON: I feel great about GraphQL.

ROB: What if I told you we could mush everything down to GraphQL.

JASON: Mush it, mush it!

ROB: Mush it! Sorry. Let's do it.

JASON: I want to get into Fauna, log in.

ROB: Can I have five seconds here? You can log in or sign up with your Netlify account, no credit card required, take advantage of our free.

JASON: I'm going to go to the Netlify account, I have two, my personal and corporate Netlify, and I'm going to authorize. Here are all of my databases. So I'm going to create a database. And we want to call Jamstack Conf 2021 swag. What regions should I use? Where are you accessing it from? Your serverless functions going to run?

JASON: I think US east, so US is probably the right call, right?

ROB: Yeah.

JASON: I'm going to create. InFALD character. Must match. Invalid character.

ROB: No spaces.

JASON: We don't believe in spaces at Fauna.

ROB: But

JASON: We've got this. GraphQL button, should I head towards this?

ROB: As good place as any to start.

JASON: I'm going to look up here. I had a suspicion, but I didn't create it. I'm ready to do this. Think about what we need. First thing thinking about our we need a claim I, email holder have a claim on a coupon code. This user has claimed a coupon. So that is what? The email and coupon code. We need the ability to load a claim. By email. And then, we also need to check if we've gone over our limit. The total claim count and finally, we need to be able to create a claim. How would we do that in a GraphQL Fauna like way?

ROB: We should probably spell that out. I'm guessing both of those are strings, right?

JASON: We've got a coupon code and a string, sounds right. Let's do a string. And that's going to be required. You need one. And we also reprobably want this to be unique, right? One entry per email. And then, for this, like, do I have to do anything with Fauna to get it to recognize this or anything loo that?

There are things to add later. But to get going, no.

JASON: OK.

ROB: Do you want the combination of email and coupon code be unique? I can't really two users don't want to use the same coupon code.

JASON: It will be the same for every user.

ROB: So let's not make

JASON: We'll make this do the thing it do.

ROB: Yeah. So before you go writing queries and stuff, there's a lot of you're going to get for free with this. We won't go into it now, but you'll get the ability to create a claim, read a claim, update a claim all of that stuff. That's going to be out generated for you. By Fauna.

JASON: OK.

ROB: You're not going to have to write that yourself. Well, create a claim, that is one of our access patterns that we have.

JASON: I don't need to define a mutation for that?

ROB: No. Just by uploading the schema, that mutation is going to get created for you. And it'll show you box section, signature of the call. Different queries and mutations generated for you.

JASON: Nice.

ROB: We'll check that whenever we check the first draft and upload it.

JASON: Yeah. Let's maybe get our queries in because we need to be able to load by email and get a total claim count. Both of which, I think, are things we can't do these on our own, right?

ROB: We can. You want to load a claim by email? That's going to be a query, right?

JASON: Get claim by email, that's going to be one of them. And that's going to return a claim. We want to get back a claim.

ROB: Yep.

JASON: And the other one, I want to get my claim count, and that is, this one's going to needs an argument, right? It's going to have to take a string. This one doesn't have any argument. So it just sends back, like, the number.

ROB: Right. This one's going to be tricky, we're going to use a little Fauna goodness on this one.

JASON: OK. So to do this can I like, can I just upload this and start here?

ROB: Let's do one thing so we know it succeeds. I don't know what's going to happen if you load that. It doesn't have any definition. I'm kind of curious. If you want, we can upload it.

JASON: We don't have time for mistakes at this point.

ROB: Add a directive resolver. @resolver.

JASON: Resolver.

ROB: Parentheses, and name and whatever you want to name it, count claims, get claim count, whatever. Account claims.

JASON: We're going to count claims.

ROB: You'll see what happens when you upload this, but that will be a resolver that we use to get whatever it is you want out of your beta.

JASON: I'm going to go in here into GitHub, Learn with Jason, Jamstack Conf, where did I put this?

ROB: I have no idea. Hello? Hello? What is this repo called? You can right click.

JASON: That's a better idea than what I was doing.

ROB: Control command R.

JASON: What?

ROB: I looked at the side bar. If you hit command B, it'll pop your files. No, you've got them on the right side.

JASON: That's the button. Reveal and finder. There we go. And I can go back into here. And I can pull this up and I can drop that thing right in there. And that's so much faster than what I was about to do. Beautiful. All right. If we pop this open, now, we can see there's create claim. Now, remember, we didn't write that, right?

ROB: No.

JASON: We wrote get claim by email and get claim count. And we defined the claim itself but did not write find claim by ID. We didn't do create, update or delete. Fauna did the stuff for us.

ROB: That's right. And that get claim by email, it knew to do that because you took one of your parameters in the type that you're returning. One of the actual names of the parameters, email. Was the parameter or the attributes and Fauna created an index for you. It was smart enough to know, OK, look

JASON: There it goes.

ROB: And as you start adding records in, you can search across that record by email and get back the entire record. If you go to docs, you went to docs to show that. You can go to schema to see other things created but not so that's for you later, viewers when you're building your own awesome apps with GraphQL.

JASON: Yeah, we can see a lot here. Get a lot here. I want to get my claim count. It's a message, function count claims was not implemented yet. So we need to define this function, under this functions tab.

ROB: That's right, provide account claims function.

JASON: This is what we saw, the error.

ROB: That's right. Instead of abort, you see that so a lambda, anonymous function, takes parameters, doesn't compute on them. That underscore means it's not going to accept any parameters which is what we want. The abort is what you saw in the GraphQL playground. We need to replace that with some thing that gives us a count of all of the documents in our collection.

JASON: Something that looks like it's a count.

ROB: That's a Sesame street reference for those of y'all

JASON: Good. Good. Moving on. I'm trying to refresh one more time to see is it you? Are you you? Hello? You're nobody. Neither of us exist. Everything is meaningless. Really? We're done here. Still Kelly.

ROB: Doesn't bother me. All right. It's like I said, worse for Kelly.

KR.

JASON: Can I write claims?

ROB: You're going to need count over a set and one way to get a set is with a built in index documents. We'll say documents.

JASON: Documents.

ROB: A count of all of the documents in the collection.

JASON: In the collection.

ROB: Claims.

JASON: Is it claim or claims?

ROB: What did you label in the schema?

JASON: Claim.

ROB: So it'll be single.

JASON: Singular.

ROB: Just takes exactly what you gave it. Look, everybody, closure. If I run this again, we get zero.

ROB: Let's test one more case, though, put a document in there. Any document.

JASON: That's what I was going to do.

ROB: Sorry.

JASON: Create a claim, right? And in here, we can do an email and we'll just do this. And here, we can do coupon code and that's going to be the coupon code. Let's create one. Let's name these. Because then I can choose it. Create claim. Anonymous operation must only oh. OK. We've got a claim. Not unique, OK, we can't do that. But if I do the G SMAL trick. I could delete these.

ROB: And from the GraphQL that was automated by Fauna when you uploaded your schema.

JASON: You are absolutely correct. I probably should've.

ROB: Let's move on.

JASON: Yeah.

ROB: Can't delete it now.

JASON: So what we're done. That's it. That's the whole thing, right? In terms of setting up Fauna?

ROB: Looks like. Check for claim by email if it exists. Let's get back in there.

JASON: All right. The next thing we're going to do send a call to Fauna and I just realized I need to this server key is going to be sensitive. Go back, go to security. Create a key. I'm going to click this button off camera. And this is a server key.

ROB: While you're doing that and storing it in Netlify, I'm going to tell everybody, hey, you can do least privilege and create roles that are only authorized to call certain UDFs, write to certain collections, et cetera. That's an advanced topic for another time. Not for today's show. Know that it's there.

JASON: OK. I have now, updated this. When I refresh, no, it still shows up, I'm leaving that page. Go back to GraphQL, bring this over. I've got the key and when I start the server, we can see that I've got my Fauna server key here. We'll be able to use that. We have the need to send a request. If you've been watching all day, this is nothing new. Fetch request, using Node fetch, which matches the browser fetch API. And I'm going to use the same GraphQL endpoint that's in GraffGraphiql in there.

ROB: It got that for you.

JASON: One of the reasons I always copy/paste out of the GraphiQL instance. I don't have to pay attention. Copy/paste my way to victory.

ROB: Worked on my GraphiQL.

JASON: We have to send in the token we created I'm going to pass it as an authorization header, prefix for reasons I don't, I don't know why that started.

ROB: I think it was a joke, it's gone too far now for anybody to roll it back.

JASON: So then, we're going to I'm assuming you're being sarcastic, please tell me that's not what happened.

ROB: I have no idea. Could be.

JASON: And this is this is a GraphQL query and any variables the body, JSON, stringified and that is how you send a request. This is a GraphQL request without a GraphQL library. Plain old HTTP request. It works fine in this use case if you're doing it on the frontend, you, you're making lots of calls or making duplicate calls, makes sense to look into a GraphQL library like Apolo, urql or something like but it's suitable where you're not going to be caching, send it over HTTP like this. Then, a quick check to make sure it works. If it's not OK. Take a peek at that in the logs. Result.status and body of error sending request so, that's our error handling, it's not robust, but it'll let us know if something went wrong. And what we get back out of our data request, check me on this. We get result.JSON. So request from GraphQL gives us back. Let's get this claim count, again, get back data and if something is wrong, like I try to make a duplicate, I already have an email in there, that's not going to work. We get data and errors. This shows that we can grab out that error. What we can do is console log any of those errors so that if something's not doing what we expect, we can go check it out. We'll make that the thing we do. This is not the serverless function, it's a way to send a request. With that, I'm going to collapse it. So let's see what else happens here. All right, so now I'm actually ready to start doing stuff, right? So the first thing that we need to do is check if a claim exists. So we're going to start with this get claim by email. And to get a claim by its email, we need to do what? We're going to have to check for the email itself in here. That's coming out of the body.

ROB: Yeah.

JASON: And then, we can pass that in here. And so, inside, we're going to do introduce some stuff, right? So we need to get out claim and the count from our data, which is what we're going to get back from the send Fauna request. And we do that by send Fauna request and the query that we want to send is going to go here and the variables are going to go in here and we just want to use this email, right? We're sending in that email, all right.

ROB: Looks good to me.

JASON: To save us time, I'm not having to write out these GraphQL queries, we're going to copy/paste them in and take a look at what they do. This is just like what we wrote, except we're doing a GraphQL variable, calling it email and get the claim by email using this email variable and if we have a coupon code, we send it back. And then, we also get the count, which is an alias, this is we're running the get claim count query, but we're aliasing it as count so we can get that back.

ROB: Get claim count query. That's my new warm up.

JASON: Yeah, unique New York. All right.

ROB: Get unique New York claim count.

JASON: Assuming we get back our claim and our count, which we're assuming this works, we can then return a coupon code, which will be claim coupon code and then our count.

ROB: I love that coalescing. What do you call that?

JASON: This is optional chaining.

ROB: Optional chaining, thank you.

JASON: Down here, we can just call this. Right? We know we're going to get back coupon code and count and if I come back down here, I can get back here const coupon code and count and those will equal wait get claim by email and drop in this email. OK. So assuming that works, what we should be able to do here is then check if a claim exists and we'll say if coupon code, then, we're going to return status code of 200 because that means everything is working as expected. We're going to send back headers of content type, we don't really need to do this, but it makes the response look a little bit nicer, we're going to go application JSON and then, we will also send back a body of JSON stringify coupon code.

ROB: That is very thorough of you, Jason.

JASON: I am trying here, I'm trying. And the third thing we can also do here because we have the count. We can check if the count is greater than or equal to 1,000, ah, ah, ah.

ROB: That's right.

JASON: I regret to inform you that is not the first time we've made that joke. It's like it's a recurring yeah, greater than or equal to, yeah, it is greater than only. So then

ROB: Only give out 999.

JASON: You raise a very good point. So I'm going to copy this so that we don't have to keep typing that. And then, we'll send back as a body, JSON stringify, and a message which I'm going to also copy/paste my message so that nobody has to watch me try not to type a long sentence. But basically, we're saying, you're not one of the first thousand people to claim a slap bracelet. That's OK. Now, we start running out. If we get here, we haven't written any of these functions just yet. I guess, actually, that's not true, we have. Because up here, we have the get registration by email. So, I guess, we can just kind of plug that in. And we're going to do a little bit of movie magic. Make sure you check the pull request if you want to see how these Tito things work. But what we can do here is get the registration and we'll await get registration by email and, again, we just pass in that email. That'll give us our Tito registration and then, if no registration exists, we can say registration, if there is no registration, we're going to return a status code of 401 for unauthorized. Again, we will copy/paste our headers. And for the body, we're going to send in another copy/pasted message here so that we can go fast. Provided email was not registered to attend Jamstack Conf. So we're giving helpful feedback along the way.

ROB: All right.

JASON: And then, the next thing we need to do is to associate the email with the Shopify discount code for the bracelet. So if we look at this one, where is it? Load or create Shopify customer, we're beginning to send a mutation that will create a customer, using the email that we set, the tag is jam slap, that's the name of the discount code and the tag. And we have the customer, we give back their ID, email, tags and check if there are any errors. If something goes wrong, the customer doesn't exist, it's duplicate, we can't modify whatever that may be. Then, this will be this will make that happen. So we pass in the variables and if it works, we send back the customer. So we can take this, come down here, how are we doing on time? We're getting close, we're getting close.

ROB: We've got 25 minutes. Ten minutes, sorry.

JASON: There's a lot you can do with an email. Once we get that customer, this is where we're going to need to do more Shopify stuff or Fauna stuff, I mean. This is where we actually need to create a claim. And that is going to be up here. In our create claim. So Rob, you're back in. What do I do next?

ROB: It's a mutation, two fields, two GraphQL variables like we did before, email.

JASON: Send Fauna request. Query and variables. And we're going to send in the email and I guess that's really it, right? Because

ROB: You want to store the coupon code. You're going to get the coupon code back.

JASON: That's right. We're going to hard code this. The coupon code is Jamstack. The coupon code is jam slap. And then, we need to have this query and the query, I'm going to copy/paste for brevity. All right. This creates claim, takes the email as a variable.

And we alias, again. We pass in the email. Oh, I had hard coded it here.

ROB: Oh, OK.

JASON: Let's write a little GraphQL. We're going to do coupon code. And that's going to be a string. And it's required and then, we're going to use it down here. As coupon code. Right?

ROB: Why not?

JASON: These are functionally equivalent. But no, we do need that. I don't know what I'm doing. Cleaning stuff up.

ROB: You're good. You're good.

JASON: So then, we get our data back, and in our data, we have coupon code, which is the thing we need. We can return coupon code and that will be data.claim and optional chain that with coupon code. So it doesn't give us an error if something goes wrong.

ROB: Do you need to select your elements from the mutation? Or is that a later thing?

JASON: We just got this one. That's what we're using.

ROB: Sorry.

JASON: Technically, we can drop this.

ROB: Yes, Rob, learn to read GraphQL. Don't ask me questions like that anymore. We're under a lot of time crunch.

JASON: Yeah. We've got our coupon code coming back and that's a good call out. We're not using the email. So we were querying unnecessary data. So we can just get the data we need, which is the coupon code. We already have the email, right? We passed that in. So then, we are going to return this. So we can drop this down, head back down here. And here is our last little bit here. Claim coupon code. OK.

ROB: Jason, can we check the signature on create claim? You looked like you were returning a claim there. I think you were only returning the coupon code up top, right? Sorry if we're

JASON: I am returning good question. I'm returning an object. And the object has a property called coupon code. The object and then the property called I just realized, I didn't check any of this customer stuff. Let's check that, as well. So we want to return a status code of 500, so if something goes wrong, and then, we want to, again, send the headers. And what's our error message this time? Tell him what he's won, Bob. There was an issue updating Shopify. Please, try, again.

ROB: I'm good with that.

JASON: How many minutes do we have left? This is supposed to be done at what time? Oh, god.

ROB: My calendar says quarter till.

JASON: Yeah. Full hour.

ROB: 20 minutes.

JASON: Let's slow this down. I thought we had 10 minutes left. We're making great time, everyone. This is good. The boop should be working. You can boop. You can boop if you want to.

ROB: OK.

JASON: You can marry your friends and boops. If your friends don't boop and they don't boop then they're not booping friends. There we go, what's up, Nikki? Let's make this, let's make let's try this, right? Let's see what we can do. I'm going to create a new one of these and we're going to go to local host. And for this one, I want to call the create claim. Claim swag. And we need to send in information, which is the email. So we're going to make this a post request. We're going to send in, we don't need auth because that's in the serverless function. And the reason it's in the function is we absolutely cannot send this to our client. If this is a client, someone could do whatever they want. It would be a huge mess. Sorry for the whiplash. I know, everybody, I was speed running so hard because I thought we were all the way out of time.

ROB: I was hanging on, man, this is great. This is great. I don't know what's going to happen when I come down from this. I'm glad Chris clicked that and it's going to be a sound effect, isn't it? So now, we have this here, we don't need to send in any authorization, headers, but we do need to send in a body. So the body that we're going to send in

ROB: Body

JASON: No. We can send in some JSON and we're going to send in an email and so, for now, we can just hard code this. Right?

ROB: Do me. Rob @Fauna.com. What else would it be?

JASON: I don't know your business.

ROB: You can use that, too, if you have questions later.

JASON: Make him regret it, chat.

ROB: You have to start your subject line with y'all, though.

JASON: Things are happening, right? First of all, busted, Rob.

ROB: See, what happened was 7:00.

JASON: Oh, my God, I love it.

ROB: Use my other email. Hold on, I know I registered for this.

JASON: I think mine is registered. You need to use rob.Sutter@Fauna.com. That's why. I use different ones for different things. The short one is for the people. The short one is for the people because I want you to be able to get me and I want you to be able to remember me. At least it proves I'm in there.

JASON: Hopefully, hopefully. So claim swag 60 is what broke first. Let's go look at 60 here. So we did not get back our create claim failed. OK. That's OK. So let's console log data and find out what it's doing here. I'm going to run this, again, and go to the logs.

ROB: Go to the logs

JASON: Claim. Argument of data type claim input is required. You know what I did wrong? We didn't include the data part in here. So we're going to pass in this data like so, and this should fix it. There we go, we get a coupon.

ROB: What? And if we go back and look in our database. Not this one, it's this one. Taterbase.

JASON: I feel like we've got we have a side project to build. And we have to record everything we do for it has to be done in our best slingblade impression.

Taterbase. Biscuits and mustard and taters.

JASON: Check it out. A document inserted into the Fauna database. It's got the email. It's got the coupon code. Now, let's go back and remind everybody that Rob did not, in fact, register with multiple emails because he's a monster. But we still get that message not registered to

ROB: Citizen of the Jamstack community. JA if we run this, again, send it, get back the coupon code and not the error. What did I just do?

JASON: What did I do? It's doing all of the checks we want. Doing all that we want. It's working. This is exciting.. I'm like, we just I know we were speed running this, but let's just take a second to recount what just happened. So, when you go the Jamstack Conf, you are registering your email and register that with Tito. We're sending off your email and checking to see, do you have a valid registration for Jamstack Conf 2021 with this email? Right? And that has to be true for you to continue to the next step. Coming back down here, you know, we're checking to see, did you already do this so we don't do any extra work. And let's do a quick check here. To make sure that if we run out of swag, it does the thing that we want. So we already have one in the count, which should mean, oh, this is going to work because it's greater than 1, isn't it? Let's make it fail. Greater than or equal to 1. Only one person gets a slap bracelet and it's Rob.

ROB: Told y'all. Told y'all.

JASON: Let's send.

ROB: He who controls the database.

JASON: We shouldn't even get to the point where we check for your registration straight up say we're out.

ROB: Right.

JASON: We save a bunch of work and don't go in to check and see if anything has happened because we don't have any more bracelets to give away. Why do the work, right? So that, safeguard works the way we want it to. Let's change that back up. Check for your Tito registration. If you're not registered, we send back this, hey, you weren't registered.

ROB: Saw that happened in realtime.

JASON: And create a customer. What I'm going to do really quick, on a different window, because I don't want to show anybody's data, no, that's not the one. Where is my is that Microsoft Edge? It is.

ROB: Curious.

JASON: The one I use that doesn't spin my fans up to 100%. So

ROB: One of those 16 inch M1s.

JASON: So we're now in Shopify, right? And here's the customer we created. And you can see down here that we've got this jam slap tag. And this is powerful, what this means is that then, when I get into discount codes, which I can't click into because I don't know what's in there and which ones are controlled and all that stuff. But this, this jam slap discount code is set up in Shopify so that you can only use it if you are a customer that has this tag applied. If you try to use it, you don't have the tag, it's going to fail. And I think you can actually check this if I go back to Jamstack Conf, let's run this, make sure it works, going to empty my cart. Going to get my slap bracelet. I'm going to check out. And this pops up over to the Shopify setup. Won't let me do a different email? How do I get it to do a different email? If I put a different email in that doesn't have the tag, then it will break. Not 100% sure to not get Shopify to wonder who I am. We're not going to do that. But if you go and try this now, remember, this is deployed, you can try to this right now. If you go in there and try to set it up, it won't work.

ROB: I'm trying it as we speak. The pay code.

JASON: It should WO. We're going to try it. We're going to go in here, go to local host 888. I'm going to add a code. We'll check it out. We are checking out when I put in my email, which let's put in a different one. Nonregistered @(inaudible).com. Are you doing the thing? Do I have to pass I have to put in all of this stuff. Oh, hey, guest.

ROB: She wants one, too.

JASON: Continue to shipping. And because this email, oh, is it smart enough to get rid of these? That's going to be a pain in the butt. Let's try a different one. What's an email that I have that definitely doesn't work? Let's go with support@learnwithJason.dev. And we'll try that, again. And I broke my discount code? Oh no! OK. I'm going think I need to go back in here to this one. Let me get this off the screen. I'm going to look at this discount code really quick and make sure nobody broke my stuff. Use once per customer. Specifically to products. Specific groups of customers. And that is what happened. Somehow, someone took off my discount code. Actually, I can show this now. Shows a fixed amount off, which is $10, the cost of one bracelet. It only applies to the Jamstack Conf bracelet. Only get the discount once. And then, it only applies to specific groups of customers, which are a saved search in here. I'm not going to show this so I don't docs anybody except myself and Rob. What you do is you can search for a tag in Shopify and then, you can save that search as a group and then, we're able to say, only people in this group can use this discount code. We've limited it to one per customer, we have a start date, there is no end date, and that's it, right? If I save this, and I take this off screen and then, we go back to our incognito mode and return to information and let's try it, again. OK, now not available to you right now. But watch this, if I go to this one, which it should be, no, I don't want to do that. Right? And I'll continue now it applies. See, so it it is smart about which email address actually works. Which is what we're after. OK. Rob, I think we did it. Wow. We've got 7 minutes.

ROB: 7 minutes.

JASON: What does everybody want to do for 7 minutes?

ROB: Should we sing a song?

JASON: Will, I'm seeing questions about Jamstack Conf. So this event was supposed to happen during Jamstack Conf itself. Jamstack Conf happened on October 6th and 7th. But we had a really unfortunate event where a bird flew into a transformer and caused a power outage at the event which meant that the live aspect of the show had to be stripped back. We just didn't have the bandwidth for it. And so that's why I have this mug now.

ROB: That was most unfortunate for the bird.

JASON: That is true. The bird had the worst time, but I'm selfish, Rob. I want my day to be great. But so anyway, the event already happened. And if you would like to watch videos, we have a play list where you can watch all of these. There are some absolute bangers in here. Single page apps from Rich Harris, it's so good. Wow, OK, that's one running away. Over 600,000 views on that one. And there's just so much good stuff. Astro did a launch, we've got really I'm not going to read out all of these but I want to, they're awl really good. This was a really, really good event. There are 30 different videos with really, really good content, you should go and watch them, it's excellent stuff. And yeah. This is a reschedule of the live stuff we couldn't do during the event itself on October 6th and 7th. So here we are. Here we are. Doing the last little bits of Jamstack Conf. And if you're enjoying this, everyone, please take a minute to, you know, do a little Tweet. Just like let people know what your favorite part of this particular session has been so far, what you've learned, what you're excited about. What you're going to try. Chat, who has used functions? Who's actually used serverless functions in apps before and, you know, let me know if you used them. And if you haven't used them, did seeing what we've done so far today, like are you stoked to use them? Looking forward to trying them? Rob, while we're waiting for the chat to weigh in, seeing some great people come in here. What beard shampoo am I using? No shampoo. Dries your beard out. You get, it's not good for your beard. Shampoo's really hard on hair, everybody. You just condition and brush. Condition and brush.

ROB: The shampoo industrial complex has you buying conditioner hot oils and treatments to undo the damage that their shampoo does to your hair.

JASON: I saw this wonderful TikTok and the whole thing was about what's a thing you didn't realize you were going to spend so much time on as an adult and it was soap. You have soap for your hair, you have specialized soap for after your put the soap on your hair, you also have soap for your face and hands and it's like, oh, man, you're not wrong. That's a lot of soap.

ROB: The old ways are the best ways. Olive oil soaps, coconut oil soaps, depending on the salt, it becomes a solid or liquid. I learned that. You're welcome.

JASON: What?

ROB: I can't tell you which ones do which. But oil, salt.

JASON: This is so good. OK. So at this point, Rob, how about this? Let's use the last 3 minutes to give people a chance to find what they should do next. If somebody wants to learn more, where should they go next? We've got Fauna, obviously, we'll say Fauna.com.

ROB: Yeah. Good resource. Where.

JASON: Where else?

ROB: We have Fauna labs on GitHub, which is a collection of sample applications, tooling for, you know, GraphQL's not the only way to access Fauna, you can access directly via clients, example applications. We're about to launch a workshop oriented all around GraphQL, I don't know anything about Fauna all the way to here are your production deployment situations. Thank you for that Fauna Labs link. Follow Fauna on Twitter and you'll see that workshop come outs whenever it's ready. For now, there's a getting started section that walks you through it in addition to what we did today and starts branching out into the power of Fauna.

JASON: Absolutely. And give Rob a follow, he did a drop there. And a little bit more here because we've been, for anybody who is confused, this is not Kelly Vaughn, this is Rob Sutter, this is Kelly Vaughn. She was on a minute ago. And she helped us set up the CART. And now, Rob, who is not Kelly Vaughn, this here, this is Rob, not Kelly Vaughn. And Rob is helping us.

ROB: I had notes.

JASON: Rob helped us put together the swag claim and all of the logistics with Fauna we needed to track coupon code usage and all of those things. Next, what we're going to do is we are going to bring on Brian Robinson from Algolia and we're going to build a command bar. It's known for search, but they also have this really powerful autocomplete library. Which if you are not familiar with that, you can see it in action. This is a way for oh, that's not actually the one. That's also a good episode, but we want to do autocomplete. Here's the one where we used the autocomplete. So get in there, check that out. But we're going to use it in a different way. We're not going to use it for search like I do on my site. We are, instead, going to use it as an Omni bar. And you can type stuff in there and it does command. Brian's going to help us set this up with Algolia with our swag site to run this claim swag from an omnibar and get our coupon code. We're going to take another 15 minute break and I'll just leave the stream running and be right back mode. Rob, any parting words before we take a little breather?

ROB: Thank you, Jason for having me, thank you everybody for joining me and get out there and build with this stuff. The best way to build and keep that knowledge in there. Thank you.

JASON: Thank you for spamming the boops, as well.