skip to content

Pushing the Limits of “Static Sites” with Sanity

How far we go with the Jamstack? In this episode, Kapehe teaches us that, if we combine tools like Sanity, Netlify, and more, the limit may not exist. 🤯

Full Transcript

Click to toggle the visibility of the 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: Hello, everybody. And welcome to another episode of Learn with Jason. Today on the show we have Kapehe. Thank you so much for joining us!

Kapehe: Thank you so much for having me. Sorry if my video is a little low quality. I don't know what's going on. Thank you.

Jason: It's great to have you on the show. I'm super-excited to have you here. For those of us not familiar with your work, do you want to give us a little bit of your background?

Kapehe: Yeah. I started Sanity at the end of July. So, it's been almost three months. And it's my first DevRel job. I used to be a technical writer -- technical engineer at R zero, super fun. And I did software development locally in Las Vegas. I live in Las Vegas, Nevada. So, I just kind of made my way into the DevRel world and I love it. DevRel is fun. I really like it.

Jason: Yeah, it's an absolute blast. So, I mean, like what drew you toward DevRel? Kind of what got you interested in doing it?

Kapehe: Yeah, so, when I was younger, I always wanted to be a school teacher. So, my internship my senior year I was a second grade teach for like the last half of every Monday-Wednesday-Friday.

Jason: Nice.

Kapehe: So, I would go and teach the second graders and it was super fun and I loved it. And then I became a flight attendant for six years. And that's just -- there is no, I want to be a flight attendant when I grow up.

Jason: Hold on, so, you dealt with second graders and you were a flight attendant. You are the most well of had prepared Twitter person I've ever met.

Kapehe: I can make a mean glass of orange juice. ( Laughter )

Jason: Excellent. Okay. Oh, my --

Kapehe: I mean,

Jason: Okay.

Kapehe: Yeah. Orange use.

Jason: That's super-cool. When you worked as a flight attendant, and then I cut you off to make my silly joke. How did you get from there to tech?

Kapehe: Interesting a flight attendant, after you've mastered the orange juice and the ginger ale, there's a stop in learning. I have to do something. I became a flight attendant instructor the last two years. As a flight attendant, you have to do training and prove you can evacuate a plane in 90 seconds, prove that you can get the canopy up on a life raft or do CPR. We have all these drills we are required to know. Even down to self-defense. We had this dummy guy thingy that we would have to punch and pretend like we're taking down.

Jason: Okay.

Kapehe: And so, it was a lot of that kind of stuff. And so, I went into that part of the education of flight attendant.

Jason: Sure.

Kapehe: And the recurrent education. I really liked that, but then I found that, again, it just kind of stopped because you do the same thing every single day. So, then I looked into web development. I went to a bootcamp, super-fun. Bootcamps are crazy. But, yeah. Did that. And then got a job right out of bootcamp doing a junior software developer for a local startup in Vegas.

Jason: Yeah.

Kapehe: And then I really wanted to combine my love of teaching from second -- like my senior year of second grade internship to combine it with coding. Because I loved coding so much. And then so, I did that, and I feel like DevRel is the perfect mix of those two. Because you are educating people on code. And I like education and coding. So, that's why I found myself.

Jason: Yeah. That's cool that you also kind of found your way no matter where you were into teaching people. And I think those are -- tend to be my favorite DevRels. Are the people who aren't in DevRel because -- you know that joke, like those that can't do, teach?

Kapehe: Yeah.

Jason: And I always hear that joke and it always kind of bugs me because I feel like some of the best teachers I have are the teachers that were like in a position where they were killing it, but they felt like they weren't contributing. And so, then they became teachers to like help other people get further and progress faster because that was a thing that they cared about. When I was in my brief stint before I dropped out of college, the teacher that made the biggest impact on me was this guy who had a startup and had made enough money that he retired at like 40. And he was like, and I felt I was just going to waste my life and die on a golf course. I came back and started teaching because it gave me some meaning. I love that. It's such a cool place to be. And I like it when I meet people who are kind of driven in that same way. Helping people do more. Like Bryan in the chat, helping other people progress is the best feeling. Speaking of other -- I'm sorry, go ahead.

Kapehe: It's like, you have to know this much to teach this much.

Jason: Yes.

Kapehe: You have to -- like as the educator, you have to know so much so that, yeah, you may not be teaching it. But if those questions come up, then you can help. And so, it's a lot of like learning on my end. Like today's dream, I've done a lot of like education on my part to hopefully be ready so that any question that comes up, I can help. But, yeah.

Jason: Yeah.

Kapehe: I like it.

Jason: I love it. There's nothing more fun than being able to just learn professionally, right? And I think that's what always draws me toward DevRel jobs or any educational effort is like what you're gonna -- hold on. My job is to learn a thing and share that with other people? That's what I would literally do for fun.

Kapehe: That's so true.

Jason: Speaking of learning for fun. I'm excited about what we are going to do. If you have been a watcher of the show, I use Sanity in all sorts of things. It's what powers the Learn with Jason website. It's also in production in a couple projects at Netlify. It's like -- it's one of my favorite ways to deal with content. We're also gonna be looking at static sites which are, you know, as you may have gathered, something is that find really, a really interesting and powerful and something that I'm really excited about. So, what we're gonna talk about today and what you're going to be teaching us is how to push the limits of that. And I'm really excited about it. What did you have in mind for us?

Kapehe: So, it's kind of like us. It's Next.js and Sanity combined.

Jason: Okay.

Kapehe: And the cool thing about it is we are going to be building a like button. And it's like, oh, it's a like button. But how do we save that content to our Sanity studio? So, it will be that real-time conversation between Next and Sanity that every time I hit like in Next, my Sanity Studio right away captures that number.

Jason: Nice. I'm really, really excited about that. Because I feel like this is also where for me at least this is where the lightbulb went off for how far we can go with the static sites or JAMstack sites. It's not just a one-way conversation. You're not just building something and putting it out there and then people get to look at it. You're building something and putting it out there and people can interact with it. And like you can take this really far. So, one example that I love to give is the overlay that you're looking at right now, got my name, your name, the name of the show, the chat going on the right-hand side. This is a static site. It's built with regular old HTML and CSS and built on Netlify. And if you use the boop emoji, unmarked evens just suck scribed, thank you so much. You now have access to the boop command. And if you use the boop emote, it's going to drop an emote from the top. All done through a static site. And that's really amazing. I love that that's possible. There it goes. Look at them go.

Kapehe: That's so fun.

Jason: So, from here, I'm going to actually just switch us over into pair programming view so that we can start looking at stuff because I am really, really excited to build this and I want to make sure we have enough time to get it done. So, this is Kap's Twitter, make sure you go and follow. Bryan, thank you for the sub. I appreciate it. What's the first thing we should do? Getting ready to roll, why should I start?

Kapehe: So, we could start up our Next project.

Jason: Okay.

Kapehe: And then from there, I'll show you how to get your Sanity. So, like we're going to show you how with any frontend get your Sanity Studio up and running.

Jason: Okay.

Kapehe: Yeah. So, let's just create a Next project. Yes, next-and-sanity. That's a good name.

Jason: Okay. Wait. How should I start? What's the right first step here?

Kapehe: So, like the create-next-app and then whatever we want to name it.

Jason: Is it like this, I think?

Jason: I haven't used this one yet. Let's see. This is a fun thing with Yarn. Where if everybody exposes a create React, create Next app, you can do create whatever the name of it is and it will work. What is your project named? Oh, did I do -- hold on. I did that wrong. I want to run it in this folder. Maybe it will let it work. Maybe...

Kapehe: Yeah. If you do the npm way, create next app with a dash in between both those words, all three of the words.

Jason: Yes, that will also work. What's up? Hey, I see Chris in the chat. What's up? Multiple Chris, Chris on code, saltburnem. Hey, everybody. Make sure this is get -- I'm going to initialize get and look inside.

Kapehe: What's that teach thing?

Jason: This is a -- it's an alias for the code command. So, I keep this on in my dot files, which I can link to here. But what this command does, is it uses a different -- it uses a different set of VSCode settings so that I don't get a lot of popovers or autocompletes or, you know, other things that are kind of distracting. It also makes the text bigger and stuff like that.

Kapehe: I see. That's cool.

Jason: Yeah. It's really, really handy. Especially when you're screencasting a lot. So, now, inside here. Here we go. We've got a package.json, and installed next, React and react-DOM. We've got some basic styling, some images and it looks like our app. Our index. With just looks like just some documentation links and stuff.

Kapehe: Yeah, so --

Jason: And this.

Kapehe: If you're really familiar with React, which Next is very -- is React. Pages and like components are the same thing. So, if you're new to Next, that's how like the pages is working in my mind is like, oh, these are my components. You know?

Jason: Yeah. I think -- so, in Nextland, if I'm remembering correctly, this one is special because this is like the full Next wrapper. This will get applied to everything in the site. And then these end up getting turned into the same thing dot HTML. This is going to be the root of the site. Like index.HTML. If we created about.js, that would be slash about. And this will be using serverless function.

Kapehe: We will be building one of those today.

Jason: Okay. I'm ready here. What should we do first? Yeah, so, we can get our studio up and running so we can get those two connected.

Jason: Okay.

Kapehe: So, if you -- so, you would need to get a Sanity account, we have to go to Sanity. io.

Jason: I think I have one.

Kapehe: Or it would prompt you.

Jason: You have the Sanity CLI installed. Let's take a look at that just to make sure it's clear what's going on. So, to get started, we would get started with the CLI. So, I've already installed this, and then once we get in. We can run Sanity init. It doesn't look like it's doing the Sanity login part. If I do a Sanity login, it will say I'm logged in. Or log me in. It says I'm logged in now.

Kapehe: And back to the code.

Jason: That's it.

Kapehe: Okay. So, we are in the root of our folder, yes. So, from here we will do a Sanity init. And this will ask us a series of questions. So, we're going to be -- yeah, creating new projects. So, press enter. And we're gonna name our project. We could do next -- or Sanity Next Studio. Anything.

Jason: Okay.

Kapehe: Because this is where our Studio is going to live. Yes, we will use the default. So, yes. Enter. And it's creating the dataset. And then because we don't want to spend too much time on like creating the schema, we're going to kind of let it create a schema for us and then we'll tweak it a little bit and add some stuff. Here we can change the name. Right now we have it as within Next and Sanity, we have it sanity next studio. You can save that path if you hit enter. If you started typing, You could update that folder name.

Jason: Got it.

Kapehe: Here we have a couple project templates. Here is where you can have a schema for movies. We're going to do blog. If we did the clean project, it would be empty and we could go within our Studio or within our Studio code and start building it there. But, yeah. So, we're just going to do --

Jason: And so, like it said it was creating a dataset, right? Where is it creating that dataset?

Kapehe: So, we're going to be having the production one.

Jason: Is this installing something on my computer or is this on Sanity's cloud? Where is that living?

Kapehe: Yeah. So, all of the data, we don't need to create a database. Sanity will take care of all that.

Jason: I love that.

Kapehe: And we will see all of our projects on the another website that we'll get to.

Jason: Okay.

Kapehe: Right now it's going to be local. But Sanity takes care of the management so you don't have to go get MySQL or create your own database. It's all here.

Jason: This is one of the thing that's just such a nice experience with Sanity is the last thing that I want to have to do when I'm building a website is stop building the website and start dealing with a Docker container to get a database. Or logging into whatever remote service and configure that database, and figure out what credentials I need and figure out how to get them into the project safely so I'm not leaking my access. I love that Sanity just did all of that and now we have our studio here.

Kapehe: And like Bryan says in the chat, who wants to spin up a server for a database.

Jason: I love it. This is great. It looks like it's done. It's live in Sanity Studios. If I LS, here it is, it's there.

Kapehe: So, if we want to get both up and running, we can do npm-run-Dev, and that will get our next project running. And if we CD into the studio that we just created.

Jason: Split my terminal. Split pane vertically.

Kapehe: So, yeah.

Jason: And it was Next and Sanity. And then Sanity Studio. Okay. And so, this is a whole other project. Like if we look at this in here, here's our sanity-next-studio. It's got its own package JSON and configs and things.

Kapehe: Yeah. If you click on Sanity JSON in that folder, this is where the project ID lives. We're going to need that project ID. There's a couple of places we can find it as well. And I'll show you both those spots.

Jason: Okay.

Kapehe: But yeah. Within our studio, Sanity.json will have all the information.

Jason: Okay. To start, I can run Sanity start?

Kapehe: Yeah, run sanity start and it will generate for local host 33.33.

Kapehe:

Jason: Okay. We've got this little spinner going.

Kapehe: Yeah.

Jason: This is also a static site, right?

Kapehe: Yeah.

Jason: Which I think is really, really cool.

Kapehe: You can even deploy this. You can deploy your studio so you can -- anyone on your team that you make a collaborator within this studio because you have to make -- you have to give rights, right? And we'll do right rights. Read and write rights for this project. But, yeah. So, yeah. Here's our studio. And let's kind of play around a little bit in here and I want to kind of show everyone how our schema is working. So, this is the blog schema that we picked when we did Sanity init. So, in here, we just have like title, we have slug, main image, body. So, if you have a blog, then this is where all your content will live. And then once you start typing stuff in, like we could do a test blog. I don't know. Yeah. Oh, hey -- yep. And then if you hit generate, it will generate that slug for you. Now author, because we don't have any author in our author schema. So, if we went back to the content.

Jason: And now, do I need to save this first?

Kapehe: It will hang out. It will just wait.

Jason: Nice.

Kapehe: Yeah. So, see author, yep. Click there. And then you can make a new one.

Jason: Okay. So, I generate. And then let's see. Is it safe to open my downloads folder? Let's find out. No, we won't worry about that.

Kapehe: We can skip that. And then bio. Boop. And then publish that. And go back to content. And hit post.

Jason: I love that it autosaved.

Kapehe: See how there's like a little pen on the right side that have? If you went back to post.

Jason: Yeah.

Kapehe: On the -- next to content, yeah. So, that's saying, like, there's edits in there, they're not published.

Jason: Oh, okay.

Kapehe: Once we publish, that will disappear.

Jason: Got it.

Kapehe: Click on that. And then within here, now we should have our author pop up. So, if we click that drop down --

Jason: Okay.

Kapehe: Package.json.

Jason: Images and categories if we need them.

Kapehe: We don't have to worry about that right now. This is the body of a blog post. So, yeah. Now if we clicked on -- see those two arrows going diagonal, click on that, that makes a bigger view. You're now in a doc. It's not so tiny and now you can work on a bigger view.

Jason: Nice. That's really nice.

Kapehe: See that plus sign to the left?

Jason: Yes.

Kapehe: Here we can add an image. And this is like an image for your blog. And this is already set up for you when we click through the blog in the Sanity init.

Jason: That's really cool. So, what do I have for corgi images? I'm sure that I have...

Kapehe: I'm sure you have some.

Jason: Yeah. That'll work. Okay. So, we've got... got an image.

Kapehe: Okay.

Jason: We're in great shape.

Kapehe: So, publish that.

Jason: Published.

Kapehe: And see how that little pencil thing went away on the right of the post?

Jason: Yeah.

Kapehe: That preview, now it's been published. And if we were to edit it again, it would bring that pencil back up and say, there are things in there that aren't published.

Jason: Oh, yeah, there it is again. Check this out. This is new, right? This just launched.

Kapehe: Yeah. This is review changes.

Jason: It's amazing.

Kapehe: The UI on this is my favorite. Because if I were to go into this right now, if we deploy this, once we do that, you can give me rights to that and if I go in and change something, you would see I was in there adding an exclamation or fixing a typo. That was just launched last week.

Jason: Extremely cool. So, yeah. So, I think let's see. There's a question about Sanity being localized. Fields and titles are customizable in the schema. Yeah, that is also really nice. Let's actually look at that a little bit. This is something that I think is a little bit of a power user feature. But it's so cool. Which is that all of the content that we're seeing, this is fully defined in code, right? Like I can control all of this?

Kapehe: Yeah. So, let's actually manipulate it a little bit and let's add something. So, this schema.js --

Jason: Okay.

Kapehe: This file has all of our schemas. Author, post, category. All of it lives here. So, if you add a new schema type. So, if you add -- instead of post or author you wanted to add projects, we can do that but we're going to edit the post.js one.

Jason: Okay.

Kapehe: And we're going to add a like schema, a like one. So, at the -- I mean, we could do in anywhere within the fields. You have an object. And then we'll name it "Likes."

Jason: Lower case.

Kapehe: Lower case.

Jason: The name is like the database name. Like what will show up in APIs.

Kapehe: Yeah. It's --

Jason: What will be showing up --

Kapehe: Yeah, it's what we'll be using in our code and the title is what they'll see on the front. That's why we want to capitalize title with the likes, capital L.

Jason: Okay.

Kapehe: And then type, we want this to be a number.

Jason: Just like that, plain English?

Kapehe: Just like that.

Jason: Okay.

Kapehe: Now, we want this likes to actually be -- to actually give an initial value. We don't want it to be empty when we start it up. If you go outside of the array of the fields. We can do this at the top of this or at the bottom.

Jason: Okay. Here, right?

Kapehe: So, do it right above preview.

Jason: Oh, above preview, got it.

Kapehe: Yeah. Just so -- visually that makes sense to me.

Jason: Yeah, works for me.

Kapehe: But, yeah, initial value with camelCase.

Jason: InitialValue.

Kapehe: And then open that up for an object. And then we'll do likes in there and we'll set that to zero.

Jason: Just like that.

Kapehe: Just like that.

Jason: Beautiful. I'm into that.

Kapehe: Now what we save that and go back to our studio. Might need to refresh it.

Jason: Did it all for us.

Kapehe: Go to the bottom. Zero is not there.

Jason: Now, that's because this post already existed, right?

Kapehe: Yeah.

Jason: So, if I create a new one, it's zero.

Kapehe: Yeah.

Jason: So, this is something that I've always been curious about and maybe you can answer it for me. Like if we create a new field, Sanity won't change those fields. Is that done for, like, safety? Or is that kind of -- do you know kind of why it doesn't edit my posts? My old posts?

Kapehe: I don't know 100%. But for me, it would be like, yeah, like a safety thing. Maybe you don't want -- so, maybe you have like a bunch of old posts and you're doing a new feature that -- I don't know. Maybe Bryan can help me? I don't know. I don't really know the full answer to that so I don't want it say.

Jason: No, it's totally fine. It would be better not to guess, right?

Kapehe: Yeah.

Jason: Because we would end up confusing people. But it's okay. Because, look. We can fix it. Now our post has zero likes. That's great. It's a new post. Nobody's seen it yet. It's not published on a website or anything. It's just in Sanity. And there was a question, is Sanity a database in itself? And I think the answer is sort of. Do you know what it's using in the background? It looks like Bryan is actually answering.

Kapehe: Yeah, there's a lot of architecture happening in the background. Much of had hosted in the Google Cloud. And the CTO, there's a link about how on the Google Cloud platform, how that's working. Yeah. And Simon is very knowledgeable in all this like -- like the nitty gritty of Sanity and what's like happening behind the scenes. So, yeah. That would be an awesome podcast to listen to if you want to know more about that.

Jason: Excellent. Okay. So, now we have written a blog. So, and I want to note, we have been maybe coding for like 20 minutes and we've already not only, like, built a basic Next site, we haven't changed anything on it, but stood it up, and built the CMS and wrote the first post in the first 15 to 20 minutes of writing code.

Kapehe: Yeah.

Jason: In addition to silly questions and derailing with silly jokes. This is why it's so cool, this new model. And why it's such a big impact for teams. If we can mess around as much as we have been messing around and still get this far in 15 minutes, that is powerful.

Kapehe: Yeah. And then the moment it's deployed and you give your teammates access to all of this, it's -- I mean, it's ultimate team collaboration on --

Jason: Should we do that. Should I just give you access?

Kapehe: You want to do it right now?

Jason: Yeah, let's do it. How do I do that?

Kapehe: So, Sanity deploy.

Jason: Studio host name, I will call it next sanity.

**Kapehe:**I think that's taken.

Jason: Preface with --

Kapehe: Some of them I name, if Kapehe is being used...

Jason: How dare you.

Kapehe: That's my name. Once you do that, go into the manage dashboard where you can give me rights and I can come in there and I can edit some stuff. And back to Next and do the whole like button thing.

Jason: Excellent. Oh, no, my Slack. Shush.

Kapehe: Boop! I love -- I love the corgi thing. I love the rainbow corgi.

Jason: It makes me so happy. I think -- I do think that that is currently -- is that still broke someone

Kapehe: The rainbow corgi? No, it just popped up.

Jason: Oh.

Kapehe: There it is.

Jason: It's been a while since we had a good corgi storm here. Hint, hint, chat. You think the stampede is back, actually. If that counter is working, I'm pretty sure it's back.

Kapehe: Yeah. So, now it's alive at LWJ next Sanity.sanity.studio.

Kapehe: There we go.

Kapehe: Cute!

Jason: And look! Look! The same thing. So, this is amazing because I ran one CLI command. And now that post is here. And so, I haven't given you access yet, but I want to show one thing that I think is really fun. Which is that like if I go in here and I go here... and then, oh, I need to restart my local server. And then when this restarts, we should see that change like already pulled down, which is amazing. And while we're waiting for that, how would I give you access?

Kapehe: Yeah. So, if we go to manage.sanity.io. And this is where all of your projects will live. So, the very, very bottom. Sanity Next Studio, yep. So, here, also, is where our project ID lives. And if we've deployed it, where it also lives. So, if you forget what you've named it, you can find it here and your project ID. Under team, click on team. This is where you can add people.

Jason: Excellent. Is it okay if we show your email or do you want me to pull this off-screen?

Kapehe: Yeah, I don't care. So, Kapehe@sanity.io. Perfect. Ooo. Admin rights.

Jason: You're in charge now.

Kapehe: I'm going to check that.

Jason: Here is our local instance. And now I'm editing local. And then I'm going back to remote. And look, it's already there. I didn't have to refresh or anything. It just showed up. That is amazing.

Kapehe: Okay. I'm accepting the invitation right now. Yes. Accept. And then I'm gonna go in and I'm going to add --

Jason: Look!

Kapehe: Oh, yeah. You see me. This is our presence API that we just -- we launched in maybe a month, three weeks ago. And so, wherever you are or wherever I am, we can find each other. So, if you hover over that, a little bit more. So, I'm nowhere. So, let me click in somewhere. So, now you can click on me and see that little link thing on the right? That will make me -- take you to --

Jason: Ooo... okay. And so, I can just spy on you while you edit.

Kapehe: Yeah.

Jason: Nice.

Kapehe: And then I'm going to regenerate that and publish.

Jason: That is so cool.

Kapehe: And review changes. You now see -- now it was just published. So --

Jason: And we can go back in time which I think is really interesting. So, here.

Kapehe: Yep. And if you hover over those, you see my name.

Jason: If we make a change that I don't like, we can just back it out.

Kapehe: Yes.

Jason: That is so cool. I love that. That is really, really interesting. This is one of my favorite features of Google Docs. I think it's the reason people still use Google Docs is the ability to do this kind of suggestion setting where you make a change. I can see it, that's not the one I want. The something like that. Not this change, let's get that out of there.

Kapehe: And you can do individual ones or all of them at the end. There.

Jason: So, question kept Kap's changes and we dumped mine. And that gives us -- like, that's fine-grained editing control which is very lacking in like -- I mean, unless you're going to get into the nitty gritty of Git-based editing. But even then, if somebody makes four edits in one commit, you can't just back out one of those four edits, you have to find them, copy-paste the of stuff you want, roll back, add it. This is kind of nice. That one-click undo for just a portion of what changed.

Kapehe: Yep.

Jason: And the time travel too. Oh, how did we write this in the previous version? I can go here and say, ah. There's the very original publish. There's the changes. That's really nice.

Kapehe: I'm going to add an image just so we can look at something pretty. This is my --

Jason: Look at that. And it showed up in real-time too.

Kapehe: As I'm watching you, I'm doing it on this screen.

Jason: That's very cool.

Kapehe: That's the monstera leaf. Corgis to Jason is like monstera leaf to Kapehe.

Jason: Definitely publish that. I'm ready to pull some content out. How to get this out of Sanity and into our Next site?

Kapehe: So, back in manage.sanity.io, I think that was a tab right there. Go to settings. And we can look at this locally. We've got to give this studio, if you go to the top, see API on the left?

Jason: Yes.

Kapehe: So, click on that. And we're going to add local host 3000 because we're going to be looking at our stuff on local host 3000. So, we've got to give it those.

Jason: Okay.

Kapehe: Okay. So, now we have that. Now let's go create our Sanity client file in our project.

Jason: Okay. So, I'm going to go back to here.

Kapehe: Yes.

Jason: And we're done in the studio for now.

Kapehe: Yeah. We've added our likes and initial value. For now, that's it for now.

Jason: Great.

Kapehe: So, now in the root of the entire folder, entire project, let's do a new JS file and we'll call it Sanity client and we'll do camelCase. Yeah.

Jason: Okay.

Kapehe: Now, we need to import the Sanity client. And we haven't done that yet. So, if we want to do an install of at sanity/client.

Jason: I'm using Yarn here. @sanity/client. I'm not installing this in the Sanity Studio?

Kapehe: Yes.

Jason: Okay.

Kapehe: We want this to be all over our project.

Jason: Okay. We've got it.

Kapehe: So, yeah.

Jason: So, now I can import.

Kapehe: Yeah. And we can call it anything. So, Sanity client from, and then @sanity-client. Perfect.

Jason: Okay.

Kapehe: And then export default, sanityClient. And open up that project and we'll do project ID.

Jason: And then I need to get that from, it's right at the top of this page.

Kapehe: You could do it from here or from the Sanity.json in the studio.

Jason: Here.

Kapehe: We can copy the dataset as well. It's production. Dataset, production.

Jason: Like that?

Kapehe: Yeah.

Jason: Do I need anything else?

Kapehe: That's it for now.

Jason: Okay. All right. Feels like magic. That's excellent. All right. All right. That almost felt too easy. I'm like, wait a minute. Did we just cheat?

Kapehe: Feels like it, yeah. So --

Jason: Next --

Kapehe: Now within the Next, every time we want to call to our data in the Sanity Studio, we just import the SanityClient. If we do a fetch, we'll do sanityClient.fetch and it will be able to read all that. And that's why we had to do the local host 3000 so that it knows when we're running it there.

Jason: Right.

Kapehe: It's just like a security measure so we're not letting our data go anywhere --

Jason: Sure.

Kapehe: If somebody gets our ID or something.

Jason: Yeah. That makes sense.

Kapehe: Both have to be there. It has to have the URL in the manage and the project ID.

Jason: Okay. Cool. So, we want to load -- I'm assuming we want to load this on this page, right? So, we can probably -- we'll do like a TODO: Get Sanity title. And down here, we'll just get rid of all of this. Right? Yeah. And then we'll say, TODO: Get Sanity content. And then maybe as well, we'll try to get the get sanity image. And I think those are the pieces that we got. Let's drop this out as well. We're going to keep this as simple as we can. We've got as few moving parts as possible.

Kapehe: Yep.

Jason: We are --

Kapehe: So, we could, if we wanted to, we could have this index be like a link -- linkable page and we can link to each blog post. Or show up here?

Jason: Yeah. We can do whatever -- we can do whatever. I'm pretty happy to go either way. I think we're aiming for proof of concept more than like real blog, right? So, we just want to show how to get some content in. But maybe creating the links would be good because it will help us show the, you know, the process. Like we're gonna get a list and then we got to show each one and so on.

Kapehe: Because the cool thing about Next that I really like. So, React, you would have to import link and like do React routing and all that stuff. Next already has this kind of built-in.

Jason: Okay.

Kapehe: And so, that's -- I don't know. It's like straight from Next to link, you just kind of import it at the top of your file and you have like the linking capability.

Jason: Next link, okay. Cool.

Kapehe: So, we could do that.

Jason: Yeah. So, then I need to get a list of the things. And so, we're gonna do this as a static site. So, in -- let's see, this is probably async, isn't it? In had Next, that would be the export async function getStaticProps. That's an API from Next so we can render a static site. Do I need to import that sanityClient? Is that right

Kapehe: Yeah, at the top of the file. And the path should be two up. Or one up.

Jason: One up, sanityClient, there it is.

Kapehe: Yeah. And down here, do post, maybe, and then wave that and do sanityClient.fetch. And then here we're gonna do groc stuff.

Jason: Groc stuff, okay.

Kapehe: This is GraphQL. It's like a query language that -- we have both groc and GraphQL. And this is how we query for our data. And yeah. If you want to learn more about it, there's a lot. We'll go over it like step-by-step what we're doing and what each part means. And this first one's just a one-liner. So, it's kind of easier to grasp. So, open that up.

Jason: Easier to groc. Ah.

Kapehe: Yeah. If we open this up, we'll do the back ticks.

Jason: Got it.

Kapehe: In GraphQL, the asterisk means all. We're going to do all, asterisk. And then we're going to do an array. And then we'll do your asterisk looks different because of your font. So, I'm like, why is it so tiny?

Jason: I spelled sanityClient wrong, didn't I?

Kapehe: Yeah.

Jason: Okay. So start array.

Kapehe: In here, we're going to look for a type. It's going to be underscore type. And then we're going to look for all the types that have post on it. So, if we remember in our Sanity Studio, our post was one of our categories. We had author, we had post. And that's where our blog posts were living. So, we're just diving into our schema and picking all of our -- yeah. All of our posts.

Jason: So, we want all of the posts. And it's whatever match this is name, right?

Kapehe: Yep.

Jason: Is it just like an equals like this?

Kapehe: It's two equals in between them.

Jason: And then quote it?

Kapehe: Visually space around the equals. I don't know if that's required. But it's just like, ah, it looks better. And then close that off. And then we can look for the slug so that we'll have the slug kind of pop-up. So, if you do an object, after, yeah, right there. And then we'll do single quotes and we'll do slug. And then with a colon after that last single quote, we'll do slug.current. So, whatever slug is being clicked on or being pulled up, it will show that one. So, right now we're trying to pull all the posts in and pull in all of their slugs. Now, next -- the way Next does it -- is after all of this, we have to turn and props to --

Jason: And then just do that?

Kapehe: Perfect.

Jason: What that means is we'll get a prop called posts. And my favorite way to debugthis stuff is always to dump it at the top to start. So, let's just do a pretag, stringify, look at our posts. And if I start this thing, when I believe is just yarn Dev. Nope. Port 3000 is already in use. Which means that I have something running elsewhere on my computer. Let's do... what can I do? Killall node. Good. Okay. So, now it should work. Okay. Server's running on local host 3000.

Kapehe: Brian, in your main terminal, you have this running. That's all right.

Jason: Not anymore I don't.

Kapehe: Not anymore.

Jason: Okay. Okay!

Kapehe: Cool.

Jason: It looks like I didn't get anything back. And that could be --

Kapehe: We might need to map over it.

Jason: Map over?

Kapehe: All of our slugs coming out. If we do post dot --

Jason: It's showing me an empty array, which has me thinking that it's not getting data back. What if we console.log back. Yeah, it's not getting any hosts back. Did I typo something?

Kapehe: Yeah, go in here and do -- just because it's giving you that warning. If you click on -- underneath use CDN and then set it to false just so we can get rid of that.

Jason: UseCdn false? Like that? Or capitals?

Kapehe: Do that.

Jason: Still nothing.

Kapehe: Let's see. How does Next want to show all this?

Jason: I'm actually kind of convinced this isn't Next. I think this is... production... you feel like this is -- we're not getting something back from our query. It's because it's coming back empty.

Kapehe: So, let's go back to the groc query. Oh, I see, I see. We need quotes around post.

Jason: Ah! Okay. Compiled successfully. There we go. Okay. Perfect. So, that's me not knowing GROQ.

Kapehe: That's me not explaining it.

Jason: Brandon, that command is with an A. That's the one for when I'm not paying attention to chat and they're giving me the answer.

Kapehe: We both are. Bryan is like post, it needs quotes. Quotes. ( Laughter )

Jason: Okay.

Kapehe: Thank you, everyone.

Jason: So, now we've got that. And I think we also want to get the title. So, if I want to get the title, do I just do like title?

Kapehe: Yeah. You could even just do title. You don't need the quotes around it. The reason we have quotes around slug is we're making slug. So, we're naming it something and making slug.current always be slug.

Jason: I broke it.

Kapehe: So, we don't have to type in slug.current every time.

Jason: Do I need a comma?

Kapehe: Yeah, comma after title.

Jason: Okay. There we go. We have a slug and a title. And down here, if I can open VSCode again, now if we've got posts, we can map other these. We'll be like, read my blog. And then down here, we can do a post.map and we'll get a post.

Kapehe: While you're doing this, I'm going to add a post.

Jason: Yes, please do. If I want the ID. The ID is underscore ID, is that right in Sanityland?

Kapehe: Yes.

Jason: I'm going to do that so we have a key for the posts we're mapping over. And for each of these, I'm going to set up an article tag. And we'll give it a key of post ID. And then inside, h2 with post.title. And I think we'll probably leave it there for now. But then I need the link. And so, Next links are a little bit weird the first time you use them. So, you do the link and an href. And then you would like to the -- let's see. How do we want to do this? We'll do it as like blog post.slug seems like a good way to do it. and then we're gonna wrap this. Might think we're done, but we're not. We have to put an A tag around it as well. That is so that Next knows what element to attach things to. I assume there's a good reason for that. It's always kind of been confusing to me. But it is what it is, right? So, this should -- I missed a piece. What did I miss?

Kapehe: Go back down. Somebody's saying there's a comma... you need a comma behind title.

Jason: Okay. So, those ones should be good.

Kapehe: That's good.

Jason: I missed something. Posts.map. Oh, it needs to return this. That's just me not knowing how to write React code. There we go. And then if I click, this is 404 because we haven't set this up yet. But it worked. It linked this to where we want to go. This is the slug that came out of Sanity. Here we go. We've got content. And look, Kap just made this new post and there we go.

Kapehe: And this is it running locally. On your local machine, running your local Next app, I'm able to work on the deployed Studio and it's just grabbing it because we've already set up that, like, connection between the two.

Jason: Yeah. It's so nice. And what's really cool, is like, yeah, like you said, I'm not running -- am I running local Studio? Yeah. Local studio is not running anymore. This is my local Dev environment is just running based on the remote code. Which is really powerful. And then we mentioned -- like I feel like we glossed over this, but we called this dataset production. But if I wanted to, we could create another dataset and call it like development or staging or something so that we could test adding and breaking data before we even touch our database.

Kapehe: Yeah.

Jason: Is this could inned on the free plan? Are we doing magic things here that cost a lot of money?

Kapehe: Yes, everything we're doing so far is magic plan. Magic plan? ( Laughter ) Yes, it's magic plan. But once you start getting a lot of data or a lot of like contributors, and you can -- you can tweak your pricing to be exactly what you need. So, you don't have to like jump super-high. You can kind of like, as you query for stuff, or as you add things. Bryan, if you're in the chat, if you would like to put a link to the pricing, that would be awesome.

Jason: Oh, I can pull it up.

Kapehe: Oh, yeah.

Jason: Let's go Sanity, pricing. Here we go. And so, free for up to three users. It's got a good quota. Let's look at the quota.

Kapehe: Yeah, click on that. And that will show you like how far you can go with that free plan.

Jason: Yeah.

Kapehe: We have the two datasets, three users. And then if you add an additional dataset, you don't have to jump up to the 199, you can just add $20 per additional one. And if you need to jump up to the bigger one, adding them a lot. You can do that. It makes it so you can tweak your pricing as you go.

Jason: And something to keep in mind, if you're building a static site, you're never going to use that bandwidth. You're only pulling from Sanity when you build the site instead of every time the page loads. These are all really, really -- this will take you a long way if you're building a static site.

Kapehe: Yeah.

Jason: Okay. So, let's get -- I think we -- the next thing to do, then, is to build the individual blog pages. So, we've got a list. And it's linking properly. So, here's our page. This part's hard coded. This part is loaded from Sanity. And if we link, it takes us to blog and the slug. So, how would we tackle this? Like we need to --

Kapehe: Yeah. We could add -- and Next calls it dynamic file? Or it's where you have it in --

Jason: In brackets, right?

Kapehe: Yeah. We could call it slug because it's looking for a slug.

Jason: This hatches the URL. The URL starts with blog, goes with slash and then the slug of our code here. And so, then we need --

Kapehe: So, we'll need the sanityClient for sure if had here.

Jason: Okay. Import sanityClient from Sanity -- sanityClient. And then we're gonna export: Default function BlogPost. And that will eventually get something. But for now we can just do like, my blog! And then down here, we have to do two things. So, the first thing we have to do is we're gonna export an async function called getStaticProps. That's what we did before, loading the data for the props. TODO: Load blog data. We have to tell Next which pages are going to get generated here. For that one, export async function getStaticPaths.

Kapehe: Yeah.

Jason: And then I think we just need to run this same query.

Kapehe: Yeah, and we can --

Jason: Or a simplified version of this query.

Kapehe: Yeah. We could do that exactly. And, getStaticPaths -- yeah.

Jason: And then remind me. How do we tell Next what the paths are?

Kapehe: Was it --

Jason: Do we like return?

Kapehe: It's like returning params or --

Jason: Yeah. So, we return -- is it just like paths? Or --

Kapehe: Oh, yeah. And then the post or the slug?

Jason: I think it would be post.map and then we would get the slug.

Kapehe: Yeah.

Jason: And just return the slug. We want an array of -- no, it wouldn't be that. It would be blog slug. We're telling it what the URL would be. I can save that. And then upon doing that, what we should see -- oh, wait. I screwed it up. Paths -- expected paths fall back Boolean.

Kapehe: Yeah, fallback false for this?

Jason: Okay. So, there is that. And compiled successfully. So --

Kapehe: And with fallback false, could you explain it a little bit. Because this is -- do you know much about fallback with Next?

Jason: No. So, what I think happens --

Kapehe: Yeah, I have a little bit of knowledge on it.

Jason: Yeah, if you've got knowledge, please. Because I have conjecture.

Kapehe: Okay. This is what you think it is. If you remember right. So, fallback false, if next -- because when it runs, all the HTML pages pop up and you have all your paths ready for the user. The browser doesn't have to go back every single time they do something. That's the cool thing about static sites. So, if it can't find a certain path, Next goes back and finds just that singular one rather than like giving a 404. Or if we do fallback false, it will just do that 404. Is that correct?

Jason: I think that's right. And the reason for that, if I remember what I read, that way you could potentially like only render the most popular 20 blog posts statically. And then if somebody hits something that is less popular, you can dynamically render it using that fallback. And that's kind of cool because it lets you do a hybrid. When you talk about static sites, one of the major limitations and one of the things that people run into, as they get bigger, they get slow to build. If you have worked on a large Gatsby codebase, the build times can go 20, 30, 40 minutes. And there are lots of ways to speed that up and you can do things to make that more performant. But the truth is, as you get more data and more pages, the amount of work goes up and that means it takes longer. So, this is kind of a hack for that. Not even a hack. It's just a clever work around. Where you're saying, don't statically render everything. Just statically render the most important stuff and then we can dynamically load everything else. That is -- it's really clever.

Kapehe: Yeah. That's fallback false.

Jason: That's fallback false! Now we're in good shape here. We've got this thing working. When we load, it loads up our posts. And then what we can do here, I'm just going to grab a lot of this code here. So, we'll get the styles. And then I'm also gonna grab this here. Let's just get this whole thing out. So, I'm going to set this up and then we'll close that H1, close that main. And then close this div. I think are they gonna fix that for me? No. Because I'm missing head. Next/head. Now are you working? Kind of? I think it should just open like nothing. Yeah. So, what we can do now is we can load those posts. And so, this is gonna be I imagine sort of similar to this, but not quite.

Kapehe: Yeah, so, this --

Jason: Get a single post.

Kapehe: Yeah. Same thing. It will be just like that. But we're going to filter down to exactly what we want. So, like, title and main image. That kind of stuff. And I think I put a main image on the one that I added.

Jason: Is it main image? Let's look at the schema. This is how I do it. So, we go to the main image and it's called main image. We grab that out. Do we need anything -- we didn't use the categories. Let's not worry about the time. To show the body, do we -- let's see. We've got like 25 minutes. Do we have time to do the body?

Kapehe: Let's skip on the main image because there's a little more to that. Let's do -- because body is -- it will just bring up body. Or we can do author name because I put my name on that. You can see that. You can do name in quotes. Or author --

Jason: Author, okay. So, name in quotes.

Kapehe: Yeah. And then we'll set that name to be author. And then do a little arrow. So, like a dash and a little carat thingy.

Jason: Like this.

Kapehe: Yeah, a single dash, and then click name, type in name. The author's name will be name. So, now we're setting that value.

Jason: That's slick, all right.

Kapehe: We'll just do title slug in name.

Jason: How do I get just the one thing? I'm going to get in params here, I'm going to get the slug will be params.slug. How will get the post that has this slug?

Kapehe: So, after the post, after that quote, inside the bracket, yeah. Do & &. And then we'll do slug.current is equal to --

Jason: Like this?

Kapehe: Yeah. And then in quotes because we forget that last time. Yeah. We'll do just like that. Yeah?

Jason: Okay. Let's give this a shot. I'm actually just gonna spread post so that we can grab like slug and name and title right out of the params up here.

Kapehe: Okay.

Jason: So, in here that means that we'll get title, slug, name. And then I should be able to do like title and then in here in our H1 I can do title. And then down here. I need to turn prettier on. Then in here I -- how do we do body? Is it just like body?

Kapehe: Yeah. So, what with need to do post --

Jason: We shouldn't need to do post stop body. We should --

Kapehe: Oh, we didn't bring in the body.

Jason: Sorry, we didn't do that part. We did -- by name. Oh, missed it. Did I do this wrong? Blog post. Oh, okay. I did something wrong. I forgot my comma! Again. Sheesh. Foiled by GROQ. There we go. And now if reload this... and then --

Kapehe: Yeah. We need that after -- so, to get -- because --

Jason: It's an array, right?

Kapehe: Yeah.

Jason: Okay. I'm destructuring now to make it an array. Hey! Look at it go! Okay. So, then if I get my likes --

Kapehe: Yeah.

Jason: From here.

Kapehe: So, because we want this to be able to have write access, we need to get a token. And this is where our serverless function comes in.

Jason: I told you to give me likes. Oh, I forgot to pull it out of here. I don't really need the slug anymore. I'm not going to get that one.

Kapehe: That's true. We don't need that.

Jason: Okay. And it didn't give me... did it have a value?

Kapehe: So, for the likes we -- and maybe Next wants to do it a little bit differently. But set a state so as we update it. Oh, you got it.

Jason: So, looks like I got it this way. And then do we want to track that in the Next state?

Kapehe: Well, we could track it and let it also link to Sanity Studio.

Jason: Okay.

Kapehe: So, we can see within our Studio how many likes something has.

Jason: Yes. And we need that part so that we can track it between refreshes. Like if I do it just the React way, which we can do really quickly. Thank you, hooks. I can do a const likes, set likes. And then we'll make that React.useState, and we can set the initial value to likes. And then over here, I can do an onClick, and we will say setLikes to likes + 1, right? And so, then what will happen here is -- oh, I double -- likeState. And likeState. Okay. So, less than as I click this, this will track. And that's really exciting. But... if I refresh the page, it goes back to zero. So, if I want to store this somewhere, how would I do that?

Kapehe: Okay. We have 20 minutes. Let's do this.

Jason: Speed run.

Kapehe: Okay. In the API folder, we're going to create. We'll do handle-like in the -- yeah. the API folder, handle-like.

Jason: Okay. I'm going to copy this for getting started. What this will give us is we get the request and the response. And so, we're setting a response status code of 200, HTTP/200, okay, and send back a JSON object. In our case, it will be likes and whatever the new likes value is.

Kapehe: Yeah. So, we're gonna want to bring in our sanityClient. And we're gonna give this a write token. Because every time someone tries to update this, it's like write access. We want this to be able to write to our Studio.

Jason: Yes.

Kapehe: So, we'll need to do a -- yeah.

Jason: A token. Now, I'm going to need to pull this offscreen, right?

Kapehe: Yeah. And get it right.

Jason: I'll get it set up and get it checked here and we'll be able to go from there. So, this is going to be a LWJ Next Write Token. Okay. I'm going to pull this offscreen while I generate the token.

Kapehe: Cool, in the.env, name it something.

Jason: So, that's generated now.

Kapehe: Cool.

Jason: And I have it copied on my clipboard. And so, what I'll do in here is I'm gonna set a .env file. And then I have this thing called Cloak. So, what I'll do is we'll call it Sanity Write Token. Or does it need a special name?

Kapehe: No, it can be that. Because we'll just use that. Yeah, that's perfect. That's perfect.

Jason: Okay. All right.

Kapehe: This -- this is cool.

Jason: So, how do I add the token to this?

Kapehe: so, we'll do like client config and then we'll do like above that. And then we'll do token is process.env. And then -- and I don't know if we have to do it outside of that.

Jason: I think we can do it either way. But we don't need to rewrite it every time someone requests. So, why not keep it out here?

Kapehe: Okay.

Jason: Okay? So, we've got that.

Kapehe: And then in here, okay. Let me just make sure that this all works. Because we're going to be using the Sanity SDK. And there's a lot of like cool things that we can add on that will take care of like the incrementing and then the save of the likes.

Jason: Okay.

Kapehe: So, we'll do -- yeah. We have request -- we'll do const and then destructure the ID. So, JSON.parse. And then we'll do request.body.

Jason: JSON -- oh, oh.

Kapehe: Yeah.

Jason: We want the ID.

Kapehe: Yeah.

Jason: And that will be json.parse request.body.

Kapehe: And you'll need an underscore before that ID.

Jason: Right. Because it's Sanity. Okay.

Kapehe: And under here, we'll do const data. And then we'll do await client. And then here what do we call it? Yeah, sanityClient.

Jason: Okay.

Kapehe: And then we'll do dot patch.

Jason: .patch, okay. Where do --

Kapehe: In here we'll do the ID. Just underscore ID.

Jason: Just as the first argument?

Kapehe: Yes. And then outside of this, we'll do a dot --

Jason: Oh, outside. Okay.

Kapehe: We'll do dot -- so, like inc. So, like increment. And we'll do within that, we'll do likes 1. So, do curly.

Jason: Like that...

Kapehe: Yeah.

Jason: Okay.

Kapehe: And then outside of that, we'll do commit.

Jason: Okay. Why do I set this client config?

Kapehe: So, where do we set that client config?

Jason: Like is it like sanityClient.client config?

Kapehe: Yeah. It should be client.config.

Jason: Oh, oh, oh.

Kapehe: SanityClient.config, sorry.

Jason: That's a method.

Kapehe: Yeah.

Jason: Okay. Okay. That's good. So, then in theory, what that will give us is -- so, we need to send in an ID. We have to post an ID. And then that's going to send a patch request which is like to not replace an -- or, sorry -- to replace a document, but to like update it. And the update we're applying is to increment our likes by one. Is that --

Kapehe: Yeah. And then the commit will save it all.

Jason: Got it. And then what we get back is that the whole post, or is it just going to be the data that changed?

Kapehe: So, in the response, we can do likes. And here we'll do data.likes so we get just that like.

Jason: Got it. So we're going to do data.likes. And so, that I think, should work.

Kapehe: And do we have to return the response underneath all of that?

Jason: That's what this part is doing is setting the response.

Kapehe: Okay. I didn't know if we had to return it. But, yeah.

Jason: So, now what we should be able to do is in here, we can set up -- so, I need to query for the ID so that we have it. And then I'm going to set up a function which would be addLike. And that's going to take -- it doesn't really need an argument. So, we'll be able to do a, like --

Kapehe: So, we want to like fetch for that API --

Jason: Yeah.

Kapehe: And a like.

Jason: Response will be await. So, I need to make this async. Will await fetch. And that's going to be API/handle-like. And then what we're going to send it as is as a post. And for the body, we will JSON stringified. And I think that's everything we need. So, then down here, we will -- oh. What we get back is gonna be JSON. So, we'll then get our response. And we'll do response.JSON. And then that's going to be an object that just has the likes in it. So, we can actually...

Kapehe: Set likes.

Jason: And then we can setLikes to be likes. And so, I should probably alias this so that it doesn't complain. Okay? And then instead of updating this down here, we can do an addLike. Okay. So, what should be happening now, assuming this all is done properly and I made no typos, which never happens, then we are adding a new function that will get called whenever we click this button. And what that will do is send the ID of the current blog post to our serverless function that we just wrote in here. That is going to grab that ID, send it to Sanity, increment the likes and then return the new likes which come back to us here. And then we're gonna update our UI with that new likes. Everybody ready to try this out? Let's see how this thing goes.

Kapehe: I'm ready.

Jason: Okay. First try. Is it gonna happen? No! Okay. My ID is not defined. Why is my ID not defined? It's not defined because I didn't get it from my props. Ah-hem! What? What did I do, Bryan. Missing ID in the -- you're correct. As usual, the chat is ahead of me. So, we've got something missing. Let's look at what happens. Try this again. I'm gonna hit this button. It doesn't like -- oh. Because we just created this function, I'm going to stop and restart the server so that we pick this up again. So, here we go.

Kapehe: Okay. Oh, yeah, and we did all that .env stuff. So, yeah, definitely this restart.

Jason: Okay. So, now. Restarting. Clicking the button. No! Okay. What went wrong this time?

Kapehe: Country expected --

Jason: API handle like. Naw, you exist. Handle like... why don't you exist? Anybody know?

Kapehe: Maybe -- positions... scroll up in VSCode terminal.

Jason: Oh! I didn't make it async.

Kapehe: Oh!

Jason: Ooof. All right. This is gonna work. Here we go.

Kapehe: Here we go.

Jason: I'm still counting this as the first try.

Kapehe: This is the first try.

Jason: There we go. Worked on the first try!

Kapehe: That's amazing! On the first try, Jason!

Jason: This is the moment of truth. If this worked properly, if I refresh this page, it's still gonna say one likes. We've done it! This is some extremely cool stuff. And so, now we are able to track this.

Kapehe: You can go to the Studio.

Jason: Yeah. I can go to the Studio and we can look at it. If I could find the Studio. Here it is. Booyah.

Kapehe: There it is. So, as your users update your -- or as they like it, you can see in your Studio exactly how many likes you have.

Jason: That is really, really cool. I think this happens in absolute real-time. Watch. Bang! Bang! Ah, it's so nice. Okay. Actually, this updates faster than the UI. Because it's like on the -- the return trip.

Kapehe: Oh, yeah, yeah, yeah.

Jason: So, that's really cool. This is very exciting. So, now we have exactly 8 minutes. Do you think we can deploy this in 8 minutes? Let's find out!

Kapehe: Let's find out! And then we'll get everyone to like it.

Jason: I'm going to Next on Netlify. Which is a really cool tool to deploy all of this. And I think should happen really fast. Let's find out. I'm going to stop this, I'm going to Yarn, add next on Netlify. And then we're gonna copy/paste this next.config.js. And put this down at the bottom. next.config.js. Drop that right in there. Okay. Then we need a postbuild hook. We can do that. So, we go into our package.json. We've got our build. Let's add this post buildhook. There it is. And then we're going to set up Netlify. So, we'll do a Netlify.toml. Drop this in there. Good. Okay. And so, now because I've got this all configured, we've got it all in -- or readyish for Git. Let's see what happens if I Git add all. Did I just add all of node modules? Oh, I added note. Get that out of there. I need to update this so include my .env. And let's include all Node_modules. And I'm gonna get add everything. Okay. So, this should be a little bit better. We've got our yarn.lock, styles. And then our Studio, we've got the config -- should I ignore this dist folder? That seems like something that shouldn't be tracked.

Kapehe: Yeah, you can ignore that.

Jason: All right. Get reset, and then we'll ignore this as well. And then let's get add all one more time. And okay. So, those are all the pieces that we want to track. We've got public, pages, good, I'm happy. Git commit. And we'll see, yolo. Then we're going to Git Cathy, learnwithjason/next-and-sanity. Good, and then we're gonna get push, origin main. All right. How are we doing on time? 5 minutes. Oh, boy. Here we go.

Kapehe: Here we go.

Jason: If this build doesn't work on the first try, deploy it later. Put it on here, next-and-sanity. Hopefully that's not taken. It's not. Then we're gonna do a yarn build. We'll do out_publish. This actually doesn't matter because it's going to be set by the .toml. Good. We're going to Netlify open. And that'll give us our site. It's building.

Kapehe: Okay.

Jason: And -- everybody, fingers crossed. A little bit of hold music. (Beautiful hold music)

Oooo... and a good note from the chat that we need to add our --

Kapehe: Oh, yeah.

Jason: Add our new site to the cores.

Kapehe: Yep. You want to make sure it has access.

Jason: Okay.

Kapehe: I like that hold music.

Jason: That's -- that was one of the very first things that we added to the show was like a user command to play hold music because I would always have some long-running process and I would just be staring awkwardly. And so --

Kapehe: Yeah.

Jason: Okay. So, the site's live. So, this is our moment of truth. Did it work? Awww... oooo... -- it didn't work. What's a 502?

Kapehe: Sanity token to Netlify?

Jason: Yes, chat, man, you are on top of it today. Okay. We're going to add our variables. And our variables are in here -- oh! Oh! Ooo -- you want to see cool stuff?

Kapehe: Yes.

Jason: This is a new one. We have a new command called Netlify env. And so, I can import my environment variable. So, Netlify env import .env, please don't show the whole thing. Oh, I totally did it. I'm going to roll with that token. But if I reload, there it is. I'm going to go and rebuild this thing. And we've got 3 minutes. Build fast!

Kapehe: Build fast! Go, build, go!

Jason: We have a Next cache plugin that I have not installed that will make this even faster. But for now, this is a small site. It should build in a minute or so.

Kapehe: Hold music. Do, do, do, do --

Kapehe: I like yours better. I'm going to clip that and make that a new effect. (Beautiful hold music...)

Jason: It's gonna work, got chat support for Kapehe hold music.

Kapehe: Oooo, yeah.

Jason: All right. We're uploading.

Kapehe: Any minute now.

Jason: Do the thing, and moment of truth! Victory! So, y'all, look at this. So, now you can all go like this post. And now, keep in mind, we didn't set up any kind of real-time. So, what I will do is go look at the Sanity dashboard over here. Look, folks are already Spamming that like button.

Kapehe: Yay!

Jason: This is so great. I love how straightforward this was. Like this is really, really nice. And so, whenever we reload this page... oh, interesting. We need to do -- oh. Wow. 400, okay, team.

Kapehe: 401.

Jason: I noticed the drawback, we're not going a client side check. We get the value it was built at and don't see the new value until we click that button. what we need to do next, which we don't have time for, is add a check to check polling every few minutes. We are already almost at a thousand likes. This post is going viral, everybody. And with that, I think we're going to call there a successful episode. Kapehe thank you so much. Shoutout to the sponsors, White Coat Captioning doing the captions for today, thank you for before here. Made possible by Netlify, Fauna, Auth0 and Sanity. Thank you for making this show more accessible to all people. Chat, thank you for hanging out. Where can people check out more?

Kapehe: Twitter.com Kapehe, and Kapehe.io is my portfolio, you can find all of my social links. And thank you so much for having me and this was fun!

Jason: Yeah, I'm glad you had a good time. I always have a good time. Chat, I appreciate you hanging out. Stay tuned, we're gonna raid. Thank you all again. And make sure you check the schedule because we've got some fun stuff coming up next week. Let's see if I can get this up in 1 second. Here is the schedule. We have Tanner Linsley coming up. That's going to be fun if you're interested in React query. I'm interested in it. It's going to be fun. And similarly, Zell come on, and build drag and drop with no frameworks. It's going to be a good week. Make sure you mark your calendar. And we'll see you next time. Thanks, everyone.

Kapehe: Thanks, everyone. Maholo.

Closed captioning and more are made possible by our sponsors: