skip to content

Sanity Studio v3

with Kapehe

What's new in Sanity Studio v3? In this episode, Kapehe will teach us what's possible, how we can get started, and even how to embed Studio into a Next.JS app.

Topics

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, everyone. And welcome to another episode of Learn with Jason. Today on the show we're bringing back Kapehe. How you doing?

KAPEHE: Good, good.

JASON: Good. I'm so glad to have you back. It's always a blast to have you around. But for folks who haven't seen you before, aren't familiar with your work, you want to give us a bit of a background?

KAPEHE: My name is Kapehe, you can call me Kap for short. That's what you'll see around. I live in Las Vegas and I work at Sanity as a senior developer relations specialist. Yeah. I have been there -- I have been there almost 3 years. I'm like hitting 2.5 right now. I can't believe it.

JASON: Time flies.

KAPEHE: I know. But yeah.

JASON: That's great. And so, what I am really excited about, like I've been a fan of Sanity for a long time. And I use it to power Learn with Jason. That's where all the episodes and schedule and everything is stored for the show. And I've always really liked the approach of making content management sort of developer-friendly without taking away the friendliness in to somebody who is not a developer and doesn't want to write code. I feel like Sanity is one of the tools that strikes that balance really well. Y'all just had a major release. Y'all released version 3 of the Studio. There's Sanity, Sanity Studio, what does all that mean?

KAPEHE: I think this is the most confusing thing to understand. So, Sanity, this is how I like kind of display it. The content, like, is where all of like the data lives. And that's where if you have a bunch in corgis in your dataset, testimony live there as JSON and from there, send to the frontend or sent to Studio. And the Studio is like the window into your content link. And the content link is where all your data lives. The update wasn't to the content link, it was to that Studio view. Now it's a different experience of your window into your data. Say you're already using Sanity and very on v2 and you want to do an update, you don't need to put any content freezes on. It's not touching your content --

JASON: Oh, interesting.

KAPEHE: It's just touching that window into your content.

JASON: Got it. And this is something that I think is maybe unique to Sanity? Maybe I'm missing it, but there's something cool about the fact that the Studio for Sanity is effectively an app using Sanity APIs the same way that you would build any other app using Sanity APIs. And I think that's really cool that, you know, you are effectively just opening up a React app that the Sanity team has built to let you interact with your data in a UI. So, what are -- what are the things that -- like, what's new in v3? What do you think is the -- like the kind of the banner highlights of people are getting now?

KAPEHE: Yep. So, we used to be on Webpack 3, now we're on Vite. That's going to be a lot quicker. And that comes out of the box. It is built -- I know this might be a little bit scary for some people. But it is written in TypeScript. If you're new to TypeScript or haven't been using TypeScript, don't be afraid of it. It is a little bit of a learning curve. But once you get it, that autocomplete, that checker is really awesome and you write better code. But it is all written in TypeScript. And one of my favorite things is that you can embed the entire Studio into your application. So, before, you used to have like mywebsite.com, and mywebsite.sanity.studio. Your Studio, your content editing window into your data also lived at a different URL. Now you can do mywebsite.com/admin. And that is your Studio. So, I think that's really awesome for teams. Because -- or like people who do like client work, like agency work and they want to send the Studio to their client. They don't need to send a whole new link. And the person doesn't have to have like remember that. All they have to remember is slash admin. And you can name it anything, like slash studio, like slash this is my content, I don't know, whatever you want to call it. But that's like my favorite thing. That's what we'll be doing today. We'll be embedding your studio into your Next.js app.

JASON: Yeah, yeah. I think this is really exciting. And this is -- I think like a pretty significant refactoring of the Studio because if I remember correctly, the way that it was written in v2 had a lot of like magic in it. And this is something that I've teased the Sanity team about in the past. It's like every project that is almost normal. Where it's like, well, it's React, except for this like partial import syntax that we invent.

KAPEHE: Yeah.

JASON: And I get the sense that in v3, that's not there anymore. It's now pretty standard like imports and exports, the way that you would do it any other app. Is that correct?

KAPEHE: Yeah. So, now when you want to bring in the Studio or you want to use Sanity, you used to have to like install a bunch of things or like import all this different stuff. And now it's just Sanity. And like it used to be Sanity start to get it up and running, now it's Sanity Dev. Npm run Dev now works to run your -- now, because it's embedded -- but like --

JASON: Sure.

KAPEHE: Everything is kind of like that modern way of thinking. You kind of don't have to change your -- you don't have to shift into a different way of thinking of how to run things or import things. It all is up to date and modern.

JASON: Yeah, yeah. And I feel like this is something that is -- what I've found to be really nice about Sanity is that what I always want to do is kind of stay in my code. Right? And so, when I'm thinking about how my data is defined, how I'm going to, you know, I want to create a custom field. I want to use the data that I have to create a derived field, whatever it is. What I've always historically had to do is either I'm using something like GraphQL where I write a GraphQL schema and then I'm uploading that GraphQL schema somewhere to configure a database. Or I'm writing a bunch of like middleware on my side where I'm making an API call and then running data transformations. And one of the things I've always liked about Sanity, I don't have to do that. You define your Sanity schema in code that lives in your project in GitHub and Sanity will pull that up and use it to define the content lake. I have been using Sanity for years, I still don't know what the content lake is, and I don't have to because Sanity did all that for me. And also, when I want to do something like a derived field, you can just write some code right in your Sanity schema to do that. Like use the value of this and then transform it like that and you get -- say your slug from your title. Or you can set a default value. I do a thing where if you append/post your JPEG to any name, it gives you a generated image. I can have Sanity do that for me instead of having to manually remember, oh, yeah, slash type poster. You don't have three layers of abstraction, the content layer, your middleware layer and your frontend. It's like your content layer and your frontend. And you can put so much of that content logic I would call it, that's living in the content layer which is really, really nice.

KAPEHE: And our engineers, they're so smart. Whenever I need something -- like I needed one of the peer dependencies to just be included in the next Sanity install. And now it's just included. And you don't have to think about that. So, like they're just -- they're really smart and thing about what the community would want. But also, listen to what the community has said that they need. So, they're always just like thinking ahead. One thing that I did forget to mention is dark mode is supported. So, you can get dark mode in your Studio. I know that's small. But it is pretty big.

JASON: You know, I feel like that drives decision making for a lot of folks. It's like whether or not you have your option for light mode or dark mode. Yeah. This is -- this is great. We got a couple folks showing up in the chat with love. Ryan Warner just upgraded to v3 and it's nice, he says.

KAPEHE: Nice.

JASON: Lowe is in the chat from your team. And then Ryan -- oh, Ryan has a question. So, in v2 I was basically forced to use Yarn. Does v3 work well with npm, PM, et cetera?

KAPEHE: Yes. Npm and Yarn are -- I use npm. So, I'm having a great time with it. Yarn is also supported. pNPM is -- don't quote me on this, but I'm pretty sure it's either done with like support or it's coming. But they are thinking about it, yeah.

JASON: Yeah. pNPM seems to be gathering steam. I don't know anything about it. I should have someone come on and teach me. I don't get like -- I'm sure that it's very cool. But I haven't yet had anybody show me why.

KAPEHE: Yeah.

JASON: Yeah. And yep. Dark mode. Yama is sold on the dark mode.

KAPEHE: See?

JASON: Excellent. Okay. So, I think at this point, all of my other questions might be easier if we can point at things. So, I'm gonna switch us over into the pair programming view here.

KAPEHE: Okay.

JASON: Let me click a button. This button. And we're gonna go over here. All right. So, before we get started, I'm gonna do a quick shoutout to our captioning. We have Amanda here today from White Coat Captioning who is taking down all these words, you can find that on the home page of the website, learn with Jason.dev. And on the video itself, there's a closed caption button that you can toggle on and off. Made possible through our sponsors, Nx, Netlify, New Relic, and Pluralsight, making this show more accessible to more people. So, we are talking today to Kap. Go and give Kap a follow on Twitter. And we are talking about Sanity which you can find here. And that is my extent of the knowledge of where we're going to go from here. If I'm gonna get started with v3, where should I go next?

KAPEHE: There is the two ways, you already have a project and you're in v2. Or there is a brand new project. Today we'll do brand new project. But I do want to share before we move on real quick, and maybe you can share this in the chat because I'm not really -- but this YouTube video is stream that Knut and Simeon just did. And it's all about migrating from v2 to v3. So, I highly recommend if you are in a v2 like I need to upgrade -- because it is getting deprecated December 7th of 2023. Like the support for it will not be around. So, we're really trying to get that push to make people migrate over to v3. Watch this --

JASON: And what are the -- and is it a heavy lift to migrate? Because I imagine because I've installed all this stuff. Is it just, here's the -- here's v3, you're good to go?

KAPEHE: So, most of it is gonna be you need to update the stuff in your package.json. And your Sanity.json is gonna be converted to a Sanity.config.ts.

JASON: Got it.

KAPEHE: So, things are just a little bit different. And then not all plugins are completely v3 ready. But you should find that most of the ones that are like the main ones, like the vision plugin, that's gonna be v3-ready. But -- and then some of them don't need to be v3 ready. Some of them, they just work just fine.

JASON: Oh, got it. Nice.

KAPEHE: Yeah. This is an hour-long video and they do an entire migration.

JASON: Great. Well, this will be helpful for me because I need to migrate the Learn with Jason site over to v3. I haven't gotten around to that yet. That might be a topic for a Tuesday stream.

KAPEHE: Yeah.

JASON: But Nextdoornate is in the chat saying that their upgrade was painless.

KAPEHE: Oh, perfect.

JASON: That is good news.

KAPEHE: Good news.

JASON: Okay. So, we've got a migration guide if we're already on Sanity and we need to upgrade. For today, we're going to assume we're going net new. I have a brand new site, I'm ready to roll. Should I start here or somewhere else?

KAPEHE: So, I'm actually gonna have us start like we already have -- let's start with Next. We're gonna embed into a Next app.

JASON: Okay.

KAPEHE: We're gonna have you do just npx, create app at latest. Because I want to use the new app directory, and you only do it if you do @latest.

JASON: Okay. @latest. We are gonna put this in Sanity-Studio-v3. We will use TypeScript.

KAPEHE: Yep. Yes.

JASON: Yes, lint, sure. Source directory?

KAPEHE: Let's not use that.

JASON: No?

KAPEHE: No. But then yes to the app.

JASON: I would like to use the app directory.

KAPEHE: Hit enter here.

JASON: Okay.

KAPEHE: Yeah.

JASON: And we're installing all of the things.

KAPEHE: So, I just wanted to show it this way to that you can really feel that it's -- it's embedding into your already-existing Next app. Or NUXT or Remix or whatever your frontend is. You already have it set up. You probably already have all your stuff. And this is how you do it with that already existing.

JASON: Got it.

KAPEHE: So, the first thing, I guess, if we want to make sure it's running. But it's running. We could -- yeah. But the first thing we want to do is install Sanity and install Next-Sanity.

JASON: Okay. So, we're going to npm install Sanity. And Next Sanity.

KAPEHE: So, it's Next -- yeah, Next Sanity just like that.

JASON: Okay. And while we're waiting for that to install, we can kind of poke around in here. This is the first time I've used the app directory in a Next app.

KAPEHE: Oh.

JASON: Don't write a ton of Next. So, this is gonna be an adventure for both of us. But the app directory is the one that's got the experimental React server components support, right? Is that correct?

KAPEHE: Yeah. It's -- so, I'm not like 100% like expert on it. But I have found that it -- and I'm pretty sure this is app-specific, app directory specific. But you can like organize your code. And everything starts running in the -- starts off running in the server. But --

JASON: Okay.

KAPEHE: But your code will be organized into separate things without naming a route if that makes sense?

JASON: Oh, interesting.

KAPEHE: And I don't know if that's app directory-specific. But I have learned that that's a new Next 13 thing. You can name within your app your website folder and your studio folder. But they won't be considered -- they're just ways to organize your code. I like --

JASON: Gotcha.

KAPEHE: And then it ships less JavaScript to the client with the app directory. So, a quicker app.

JASON: Yeah, yeah. Always nice to ship less code.

KAPEHE: Yeah.

JASON: So, I have my Sanity and my Next Sanity set up. And I'm ready -- I'm ready to roll.

KAPEHE: Cool. So, if the first file we want to create is Sanity.config.ts in the root.

JASON: In the root. Okay. So, I'm going to -- new file. Sanity.config.ts. I switched to an ergo dox keyboard that moves the keys around and went down to 3 words per minute. I tested yesterday, I'm back up above 60 words per minute. Until people are watching. When I stream now, I can't type at all.

KAPEHE: That's okay.

JASON: All right. So, we've got our Sanity.config.ts.

KAPEHE: All right. We want to import the desk tool from Sanity/next -- or Sanity/desk.

JASON: Import?

KAPEHE: Import, and desk tool in the curlies and this desk tool is the plugin that is our Studio. So, it will -- if we didn't have this, we wouldn't be able to view our studio at all. So, Sanity, and then slash desk.

JASON: Desk. Did I do this right? Is it camel case like that?

KAPEHE: Yep. Perfect.

JASON: Okay.

KAPEHE: And then from here, we are going to do an export of config we are going to create. Import const config and open up that object. And we're gonna have a list of things that this will be specific to your project. So, if you are following along, or if you do this in the future, know that some of this will be the same as what you have, but some of it will not. So, the first one we'll do is project ID. And I is the only one that's capitalized in Id. Yep.

JASON: Okay.

KAPEHE: And leave that right now --

JASON: That's the one you sent me earlier. Oh, gotcha.

KAPEHE: I guess we can put this in now. I'll just touch on this quick. Project Id, you can get your projectId in different ways. If you want to head back to Sanity's website, Jason, I'll kind of like show that. So, if you click on "Start building."

JASON: Let me make this bigger so that everything is not collapsed. Okay.

KAPEHE: So, this is how you create a Sanity project. So, if you scroll down just a little bit, you'll see the command that you need to get Sanity -- oh, sorry, right there. That -- go up a little bit.

JASON: This one.

KAPEHE: Yeah. Or the npm create Sanity. So, that npm create sanity at latest, that is going get you a v3 Studio. You could just do Sanity at like npm create sanity@latest, and you could answer all the questions, but that kind of answers that for you.

JASON: Got it.

KAPEHE: But then you can have all your Sanity code live somewhere else. But you'll also get a project Id with this command. So, you do need that projectId. And that's what I've already done for us. I've already gotten that projectId, but if you need to get your own or have one, you can use it. Once it's done and created then you have your manage dashboard, that's sanity.io/manage. And that's where you can see all your projectIds. If you need to create one, create it this way with that command. If not, then you can use any that you have laying around. So, we're just gonna use one I have laying around.

JASON: Great. I'm gonna drop this in the chat. If anyone wants to go get one of those, they can go build up a project. And I'm gonna copy-paste the projectId that you sent me earlier and put that into our configure.

KAPEHE: Perfect.

JASON: It's gonna look something like this, but not exactly like this. This is not secret, right? This is the public reference of your studio.

KAPEHE: Yeah. Nobody has access to it because -- oh, I'll have to give you access because it's -- I only have access to it. So, you don't need to ever put these into like an environment variable situation. These all can be just like this.

JASON: Okay.

KAPEHE: And then later on I'll -- I'll give you access so you could kind of see. But yeah.

JASON: Sure.

KAPEHE: For sure. So, the next line, we'll do dataset. All lower case. And then that will be production. So, it will be in the production dataset. And then API version. And then it's camel case --

JASON: This?

KAPEHE: Version -- yep. And then we will use -- let's do -- I mean, you could do any date. You could also leave that blank. Do 20 -- we'll do the one I have written down. 2021-10-21.

JASON: Okay. And this is -- this is like for folks who haven't seen this before, this is like the release date of the version. And if you leave it blank, it will just use the latest version, is that right?

KAPEHE: Yeah, we should leave it blank and see what happens. Let's actually, leave that blank. Let's get rid of that.

JASON: Can I just delete it all together?

KAPEHE: Yeah. Because that's an old date. I actually don't know why I have that old date. So, then we'll do title.

JASON: Okay.

KAPEHE: And title is anything you want to name your Sanity Studio. So, this will just show up in the upper right left-hand -- or upper right left-hand? Upper left-hand corner of your project --

JASON: Got it, got it.

KAPEHE: Of your Studio so we can call this -- yes. Perfect. Corgi Fanz. And then basePath with camel case on that.

JASON: Base --

KAPEHE: Yeah. And this is also where you can choose your own. We could do slash admin, slash studio. so, this is where your studio will live in your URL.

JASON: And you can put -- this can be whatever you want. But... if I'm reading into the future properly, this does not usually put the studio at that URL. This is telling Sanity that it will live at that URL so that it doesn't break URLs within the Studio. Is that correct?

KAPEHE: Yeah. It's like when you go to -- yeah. When you go to /admin, the Studio will live here. That's why -- sometimes -- because I was using /studio for a long time. I think and admin is more universal and kind of a little more like intuitive.

JASON: And we can go full chaos here if we want to confuse the heck out of everybody.

KAPEHE: Yeah, yeah. Exactly. But yeah. You can do any -- any path that you want. But this is just telling the Studio when I go here, show yourself.

JASON: Got it, got it, got it. Okay.

KAPEHE: And then the last line is plugins. And that will just be using our desk tool that we imported above. And that is going to be an array of plugins. In our case --

JASON: We drop it in like this? Or did I do it wrong?

KAPEHE: So, add parentheses. Because it's -- it's a function that you're calling. It's this desk tool function that you're -- perfect. So, if we were to start adding in more plugins to our project, we would do it here. And we would just list 'em. And then we would add it to this plugins array and just put a comma after that desk tool and then just keep chaining them on.

JASON: Got it.

KAPEHE: Which is really easy. So, I'm glad --

JASON: Yeah, it's really nice -- I do think that's one of the things that is -- it's pleasant about Sanity. It's got a very good -- like the plugin system is well-made. It feels easy to use 'em. And if you do ever dig in, I've written one Sanity plugin for v2. And assuming there weren't major changes to the way you write them for v3, it's pretty painless. It's nice. Good documentation.

KAPEHE: Yeah. Yeah. The people working on the plugin stuff, they're awesome. So, they'll love to hear that. Okay. So, the next thing we want to do is lets -- let's tell Next to use this -- like to recognize this Studio. So, this is good. This is all done. But we're going to go into the app folder. And create an admin folder, a dynamic index folder, and then a page.tsx. So, admin --

JASON: Okay. You're gonna have to remind me how the dynamic index works.

KAPEHE: Double bracket, three dots --

JASON: -- boys.

KAPEHE: Yes, square bracket, three dots, and then close the --

JASON: Wait, I've got an extra square boy.

KAPEHE: And then index in after the dots.

JASON: Oh, I understand. Okay. So, like this.

KAPEHE: Yeah.

JASON: And that's the folder name.

KAPEHE: Yeah. And in that, we're gonna do a page.tsx.

JASON: Page.tsx.

KAPEHE: Something you'll notice in Next 13, there's a lot of JS, TS, whatever it is you're using. There's a lot of them. So, it's good to like keep things organized. Or just rename it so it makes sense for you. But I'm just gonna stick with page.

JASON: Okay.

KAPEHE: So, in here at the top, we'll do use client.

JASON: Is this magic? Like this?

KAPEHE: So, do -- no. So, we'll do the --

JASON: No.

KAPEHE: Yes.

JASON: All right. Start again.

KAPEHE: Yeah, start again. So, we're gonna do -- so, the -- and I don't really understand this 100%. I just know that you need it. But single quote, use, space, client, single quote.

JASON: Oh! So, we're like telling Next some stuff.

KAPEHE: Yeah.

JASON: Okay.

KAPEHE: And then from there, then we're gonna be doing more Sanity stuff. So, let's import. And then we'll do -- so, we'll do curly braces, Next Studio. And then it's capital N, capital S, Next, capital N. Yeah.

JASON: NextStudio.

KAPEHE: That's a tricky one. That comes from Next-Sanity that we already installed /studio.

JASON: Next Sanity/studio. Okay.

KAPEHE: So, next components are by default server components. This use client that we did tells Next JS so render in the client since it's not ready for server rendering.

JASON: Got it.

KAPEHE: We have one more import. And we just want to import that figure that we just made. Import, and then the path should be one two, three of the dots?

JASON: Up one, up two, index, admin, app. you're right. And then we get the Sanity config.

KAPEHE: Yeah. Perfect.

JASON: Okay.

KAPEHE: And then are from here, we just to want return that Next Studio that we just imported. So, we'll do export default function and then we'll call it StudioPage for that function. And then open that up and do a return.

JASON: This?

KAPEHE: And then in that NextStudio. And then config, like right next to NextStudio, config is equal to, and then in curly braces, config. Yeah.

JASON: Okay. So, what we are doing is we're importing a React component from the Next Sanity Studio and then we're passing in the config that we defined in our Sanity config which is gonna tell this Studio component to use our project with the -- the admin path and all the things that we wanted. And then by defining this, we're saying this is the admin path. And then we've got this kind of dynamic catch-all that's gonna redirect all traffic under admin to this Next Studio component. Am I right?

KAPEHE: Yes.

JASON: Okay. So, is that --

KAPEHE: This should be it.

JASON: What?

KAPEHE: If you run npm run Dev and go to localhost/-- we stuck with admin, yeah?

JASON: We did stick with that.

KAPEHE: Localhost/admin.

KAPEHE: Okay. Go out to 300.

KAPEHE: Fingers crossed.

JASON: Here, slash admin.

KAPEHE: Oh, I need to give you permission.

JASON: Oh, that makes sense.

KAPEHE: It might make you log in. Okay.

JASON: Things are happening. Here is my loading. Okay.

KAPEHE: Yep. Let me give you permission real quick.

JASON: And dark mode appears to be hooked to my preferences, which is nice. I have my system set to dark mode so it loaded in dark mode.

KAPEHE: What email would you like me to send that to?

JASON: Send it to Jason@Lengstorf.com, I think I have a Sanity account so it should be all hooked in that way.

KAPEHE: Okay.

JASON: Do I need to go anywhere to accept it, or should I just log in?

KAPEHE: You should have to go into that email they -- it sends you an email and then you have to go and accept that. So, what I just did is I went to manage.sanity.io. And I went into my specific project. So, when you do that, you'll go and you'll see a huge list of all your different projects that you have. I guess mine is huge. Because I have a lot of different projects. But yeah. You'll click into members. And then you'll add -- you'll invite project members. And that's what I did here.

JASON: Is this gonna show anything sensitive if I click accept on screen. It shouldn't, right?

KAPEHE: It shouldn't, but I'm sorry if it does.

JASON: Fingers crossed, chat, no hacking. And here we go. Okay. So, now I'm in. I can see that we're the two members in this project. We get some basic data. And then here's that project ID right there if you need it.

KAPEHE: Yep.

JASON: So, great.

KAPEHE: So, actually, while you're here, click on API.

JASON: API.

KAPEHE: And see COV origins. I have allowed localhost 3000 and localhost 3333. When you deploy and you have your domain setup, make sure you come here and you add CORS origins for every URL that needs access to your data. So, that is something to keep in mind.

JASON: Got it.

KAPEHE: We will not be deploying. But if we do, then we'll come back here and add that.

JASON: Got it. Great. So, I'm gonna close this one down. We're gonna come back here. I'm going to log in. And -- yes, I am.

KAPEHE: Maybe do a refresh.

JASON: Maybe it needs to be Google or something. Okay. Sign out. GitHub. I know I'm definitely using either Google or GitHub to log into my Sanity account. Okay. I'm in. Here's my desk.

KAPEHE: Yay! Perfect. And it says Corgi Fanz.

KAPEHE: There it is. No document types. We haven't written out our schema. Which is exactly what you should see. You when you did npm create Sanity@latest, if you had a define with predefined schemas, that's in the questionnaire. I chose something that was blank. But yeah, this is exactly right. So, everything is good.

JASON: Excellent, excellent. Okay. So, I am --

KAPEHE: Now let's add schemas, yeah?

JASON: Yeah, let's add some schemas. I see Chris is in the chat. What's up, Chris? Chris is stoked about Arc browser. Yes. I am stoked about Arc browser. It's my daily driver for the last 3 months or so, I love it.

KAPEHE: He's trying to get me on it. I'm not sold yet.

JASON: I'm not here to do a pitch. But I'll tell you what, I've really loved like the fact that I have these and then you can kind of create these new spaces. I don't have any shown on this side. But basically, you can pin stuff and then like swipe back and forth between the different space. So, I have like my personal stuff here, I've got my work stuff here. I've got Learn with Jason stuff and then you can pull out these side windows that have nothing. When I'm doing a show, it's not showing all the tabs that I have open in my main browser.

KAPEHE: Okay. That's cool. That's cool. Okay. Well...

JASON: All right. Sales pitch done for Arc browser. Go check it out. I do have a few invites if anybody wants 'em. I can hook you up. But great. I'm ready to write a schema. So, I'm back in here and I've got two things open. I've got this page, which is showing the Studio. And I have the feeling that I never need to touch this page again. Is that correct?

KAPEHE: That is correct. That is done.

JASON: All right. Closing that one down.

KAPEHE: So, there are two ways to do your schemas. I'm gonna show you the way that makes it so we are not creating another folder. But you could create a different folder where all your schemas are living. So, depending on how big your project is, or how far you think it will go, that would definitely be the way. Like you want to like take it out and then import them into this file. But I'm gonna show you the way where you can just do it straight into this file. And you can have like a really quick project up and running. But yeah. So, we'll do it right in here.

JASON: Okay.

KAPEHE: And underneath plugins, we will type in "Schema." And then open up an object.

JASON: Okay.

KAPEHE: And in here... we will start writing out our first and only schema for this project. So, it will be types: And then we're gonna do an array of types. In our case, it's only gonna be one. And one more, we're gonna do a curly within the square bracket as well. If you want to go up and add that curly. Yeah. And then we'll do -- so, each -- each type needs a name, a title, and a type. So, just remember that when you're writing out your schemas for Sanity. Name, title, and type. So, we'll do name, title, type here. And because this is like our parent type, this is going to be our document type. And so, this type is gonna be document. And that's gonna be what we -- this is like the beginnings of our like structure.

JASON: And so, when you say "Document," document is like what would show up on the left as like a page or a blog post or a like portfolio entry. It's kind of like the big bucket that you would put content into, right?

KAPEHE: Yeah, exactly. We'll see it on the most-left pane in our studio. And then we are going to add a fields array to this. And then within each document type, we'll have different fields. And so, that's when you can start creating. But this one, this is like our parent document type. And we can name this anything we want. We can name it corgis, we can name it... yeah.

JASON: Oh, and name is like the system ID, right? So, we can keep it lower case?

KAPEHE: Yeah. So, title will be what you see in the Studio. So, you could -- usually you want them to match. Like name and title to match. But yeah. Name is going to be like -- like the ID for it. And so, this is gonna be more like the code side of it. Title will just be the frontend Studio side.

JASON: I have a philosophical question for you.

KAPEHE: Okay.

JASON: When you have a document type in your schema, is it better -- and "Better" is a very heavily air-quoted subjective better -- to make it plural or singular? Because later we're going to use this ID to search. So, when I'm looking at my corgis, I'm gonna get back data that's keyed with the name. So, logically, if I'm looking at this, am I gonna be doing like corgis .map? Or am I doing corgi.title because I've got an array and each one is called a corgis?

KAPEHE: Do you want to know what I put when I typed out this code? For title, corgi, singular, and then title, corgis.

JASON: I think that makes sense, each instance of the document is called a corgi. Logically, that makes sense to me. But when I'm displaying it, I'm looking at a list of corgis on the website. So, plural makes sense to me there. This is one of those things where it's so subtle. Why does it matter? Oh, but it matters so much.

KAPEHE: Yeah. Yeah. Generally I do like singular name and plural title. That's kind of what I want to stick with. But we want the dashboard to say corgis because that makes sense in a content editing way.

JASON: Yeah. And so, if I save this, does this create a document? Or does it need to have something in it first?

KAPEHE: You know, I've actually never done that. I've always just continued the whole schema. Let's see what happens.

JASON: Live experimentation. Here we go. Okay. So, I've created a document type. I'm going to refresh the page and we're gonna see what happens. And it says... gotta have fields.

KAPEHE: Okay.

JASON: You can't just ship an empty array. I'm going to take a hint and add a fields array here.

KAPEHE: Fields, and within this, just an array of objects. The first one, open up an object and do name, title, type. And this will be corgis name, or... this will just be all --

JASON: Like the name --

KAPEHE: The content that we want for our corgis.

JASON: Name and what are my type options? Is there like a?

KAPEHE: There's a full list, if you want to pull it up real quick. For this one, we will do string. But if you Google for Sanity schema types.

JASON: Schema types. Schema field types?

KAPEHE: Schema, yeah, do that one.

JASON: Okay. And so, this

KAPEHE: This, no.

JASON: Wait, am I missing the full list?

KAPEHE: Go back up. Go back to that search. I think we clicked on --

JASON: I clicked on the wrong one. Schema field types.

KAPEHE: Just do the one that says -- oh. Get rid of field types and I think there was one that's just called schemas. And that should be it.

JASON: Schema.

KAPEHE: Yeah.

JASON: Schema. Schema definitions.

KAPEHE: Yeah. Right there. That schema types list.

JASON: Oh, here we go. So, we can do array, block, boolean, date, geo, that's cool. Reference we can talk about later maybe. So, these are all things that make sense to me. Looking at this list. I'm going to want for the name, probably a string.

KAPEHE: We're going to do string for this. If you click into one, you'll see -- like you see how it's required. Like that -- the name and the type. Title, I guess, is not required.

JASON: Got it.

KAPEHE: But it is necessary.

JASON: I guess it would just give us this, right? And then that would be -- who wants an uncapitalized field name? Absolutely no.

KAPEHE: Boo.

JASON: So, I'm gonna throw one of these in there.

KAPEHE: Perfect. And then -- oh, go ahead.

JASON: What else do we want? We've got the name.

KAPEHE: Yeah. Copy and paste that to make another one. And we'll do slug for this.

JASON: Oh, come on. I used to -- I used to have a shortcut that I remembered that would just duplicate a whole bunch of lines all at once. I've absolutely forgotten what that shortcut is on this new keyboard.

KAPEHE: The type --

JASON: Got it. This is something that I think is really cool about Sanity, but I don't know how to do off the top of my head. If I want the slug to autogenerate from the name field, I can just tell Sanity to do that, right?

KAPEHE: Yeah. So, underneath this, type in "Options."

JASON: Options.

KAPEHE: And then do a colon, and open up curlies, and then do source, colon, is name. And this is gonna be lower case name. Because that is the -- the key name. Yeah. So, just like that. So, now --

JASON: Slick.

KAPEHE: When we type in -- and you could reference this to anything. Like you could have the -- I don't know what you would do. But yeah. That is just telling it to look at the name. And we'll hit like a generate button when we are in our Studio. And it will just generate whatever is in the name and it will be a nice, pretty slug for you.

JASON: Excellent. Okay. So, we got a name. We got a slug. What else we need in here?

KAPEHE: And so, we can copy that one because we're gonna do options again.

JASON: Okay.

KAPEHE: And then... we will do for this one, we'll do image. So, name, we'll just do lower case image, title, upper case image. Type will be image. So, we also have an image type. Can then options. We're gonna get rid of source. And we're gonna put instead hot spot and colon and then true.

JASON: Hotspot, camel case?

KAPEHE: All lower case.

JASON: Okay.

KAPEHE: And true.

JASON: True. Okay.

KAPEHE: And hotspot and crop is like one of my favorite things in the Studio. So, I can't wait to show that off. And then at the very bottom, we will do a portable text editor. And in that, we will be able to write all the things we want to about our corgis. So, we can copy -- we could copy image. And we'll just delete some stuff. But name, title, type. We'll do name as content. Title is --

JASON: Content.

KAPEHE: Content. Type will be an array. And then underneath that --

JASON: Type is -- oh. Array.

KAPEHE: Array, yep. And then underneath that, of, so, an array of, colon. And then do square. And then do curly. And then type, colon is block. With quotes. And so that is --

JASON: And blocks are the portable text like building blocks.

KAPEHE: Yeah. So --

JASON: Okay.

KAPEHE: So we'll be just in an editor. When you look at it, it doesn't look like blocks. It will look just like a regular text editor. But when you are in the JSON version of your code, all of this is being saved as data, it will be saved as blocks. When you start adding bold or adding bullet points or all that kind of stuff, all that will be saved as JSON and it's also saved as blocks. So, this is the block type.

JASON: Got it, got it.

KAPEHE: But yeah. Now we should be able to save that.

JASON: Okay. So, that is saved.

KAPEHE: Go create some content.

JASON: All right. So, let's reload this page. And now we should -- assuming I didn't typo anything -- have our desk. And this is in our NUX site, which is a departure from what I do. Like I log into a like .sanity.studio link. Being able to do something like learnwithjason/admin is a little improvement that I think will be great. Now that I've added this, I can see corgis. And we have no documents so I want to create one.

KAPEHE: Yeah.

JASON: And look at our beautiful input form that we just made with a little bit of copy. That is wonderful. All right. So, chat, start coming up with corgi names because I'm gonna go to Unsplash and find corgi photos. And I need you all to name these dogs. So --

KAPEHE: Aw, cute. Oh, my gosh. Look at the one by the water.

JASON: All right. Here we go. So, this is our first corgi. I'm going to -- can I just copy/paste this image in? Because that would be neat.

KAPEHE: Yeah, copy and -- yep.

JASON: I can just paste the image. Aw, I love that works. Beatrice. All right. Beatrice is a good -- that's a good corgi name.

KAPEHE: Beatrice, that's cute.

JASON: We've got this generate button so it pulls in the name. I love that. And --

KAPEHE: And then you could type in anything you want about this corgi. This corgi loves water and looks like it's at Crater Lake. So, maybe it's an Oregon dog. I don't know. Jason, do you think that's Crater Lake?

JASON: I don't know. See if anybody claims us wrong. It's the Internet, we can do whatever we want.

KAPEHE: That's true.

JASON: And another paragraph down here and say, like, Beatrice thinks you're cool. All right. So, now we have kind of two -- two blocks in our -- I think two blocks, because I made two paragraphs.

KAPEHE: Yep.

JASON: And we have our name, our slug and our image. And what if I want to like add alt text and stuff? Is that already in here?

KAPEHE: Yes. We can do alt text. Let me show you how to do that. So, if we did -- so, if you go back to the --

JASON: Oh, I clicked a button.

KAPEHE: Oh, yeah. We can do hop on crop too right now.

JASON: Let's do hotspot and crop because we have that open. When I click this button, make this a little bit bigger so we can see everything.

KAPEHE: Yes. This is one of my favorite things. You can upload one image, but make sure that one particular spot in your photo is always shown in any like ratio. So, yeah. That little dot makes it so no matter what -- and you can see the like little displays, like the little previews at the bottom. No matter what, the dog's face will always be in view. You don't have to mess with that on your frontend, it will just always show that. And I love that.

JASON: What is -- what does that one do? Oh, cool.

KAPEHE: The dot is the hotspot and the square is the crop. So, you've cropped it really small.

JASON: Oh, so, I don't need to actually crop is at all. I can leave the crop alone and I can just hotspot on the corgi's face.

KAPEHE: Yeah.

JASON: To make sure that the corgi shows up. Wow. Look at that.

KAPEHE: Isn't that fun? I love that feature.

JASON: That's really cool. Okay.

KAPEHE: Yeah. You upload once and you have all the ratios taken care of because you don't have to worry about the bottom of the image showing up only and that kind of stuff. But yeah.

JASON: This is -- this is great. Okay. So, I'm gonna publish.

KAPEHE: Cool do you want to have the alt text?

JASON: Corgi -- yeah, let's go back and add some alt text.

KAPEHE: So, if you go to the image object. Yeah. Under... under options. So, yeah. So, if you go up one. Yeah. And then right underneath, outside of the options object.

JASON: Outside.

KAPEHE: We're gonna do fields. We're creating a nested fields array. Anytime, title, option would be alt, and title would be alt text, whatever you want to call it. And then type will be string.

JASON: Okay. So, we got that.

KAPEHE: Just like that.

JASON: And reload the page. And now, look at that. A little group of alt text. And we can say Beatrice the corgi sitting by a lake and smiling for the camera.

KAPEHE: Do you actually have corgis? I really hope you do.

JASON: I -- I don't. I don't have any pets. We -- we travel enough that I am like, I don't want to -- I feel like if I got a pet, I would be volunteering my parents to have a pet like a third of the time.

KAPEHE: Yeah.

JASON: And I don't think they would appreciate that.

KAPEHE: But the corgi is the dream.

JASON: A corgi is a dream. Assuming I figure out a way to get a robot that sweeps up corgi hair five times a day. Because they shed a lot.

KAPEHE: I see. I see. Okay. The corgi dream. So, yeah. That is our Sanity Studio. All set up with the schema types. And we have content in there. Now, if you go to -- see those -- those three dots at the upper right-hand corner of Beatrice's little pane? Very top. Very, very top.

JASON: Here. Yes.

KAPEHE: Yes. Those ones. And you click on "Inspect." This is --

JASON: Ooo!

KAPEHE: This is the -- we can look at the broad JSON version of it, but there's also the parsed version. This is how you content will look in the content link. So, it's just saved as JSON. So, if you go -- let's find our blocks. Yes, there's one, and this corgi loves water is another one. And that's all within the content. It's really important to know about this three dot thing. Because sometimes when you're trying to query for your content, you want to kind of understand what's going on. So, that's like a little tip.

JASON: Yeah.

KAPEHE: Another little tip that I actually find most people can't find this. But if you want to delete something, right next to the publish button, see that little arrow pointing down.

JASON: Ah, you can un-publish, I can drop my changes. Like I added this alt text so I can dump that. Duplicate is really cool. I can see that being really useful, especially if you're doing blog posts where a lot of the metadata stays the same and you need to update. I'm the author, the author photo doesn't change. A lot of these details don't change when I go across. That's handy. And let me see... so, I can publish. And I saw another thing up here, which I think is worth showing which is that you can review changes.

KAPEHE: Yeah. SHELLEY: And that is really cool where you can see like everything that was done. And I don't know if you have this open. But since I'm in here, do you want to show presence.

JASON: Well, because you're running locally.

KAPEHE: Wouldn't it show if you were editing, though, if we were both in the same doc? or is this...

KAPEHE: I guess we are in the same project ID. Let me see what happens.

JASON: This is the sort of stuff that I find to be absolutely magical about Sanity. Is that it's -- it's just got this ability to allow like multi-player editing of documents. That, you know, I haven't tried this in v3. So, I might be -- oh, yeah. Here, look!

KAPEHE: Jason, it worked. That's so cool. We're both local.

JASON: And also if you go into Beatrice and start editing a field, it will show me that you're editing that field.

KAPEHE: Yeah. So, you'll see me. There -- in the name.

JASON: See? So, this -- this is really freakin' cool. How magically this works. Like I'm local. And you're also --

KAPEHE: And I'm local.

JASON: So, we're collaboratively editing on a document that we are both running locally. This is not published somewhere. So, that is -- this is something that I find to be absolutely wonderful about Sanity. Is that it does this. And the other cool thing, too, is like, you know, when we were configuring this dataset, I set it as production. But you can create like a Dev -- Dev dataset. So, you and the other developers on your team can have Dev dataset that you can go in and just break and do whatever you want with and not worry about production. But because of this live presentation, even when you're editing locally, you and the Dev team can stress test, what if we all try to edit the same field at the same time? You can do this without blowing up your production dataset. It's a cool feature that I definitely feel is worth calling out and showing. It's really nice. And you can see where people are working. If we are all pushing towards a launch. Kap is editing the -- I'm on the documentation, someone else is in the founders philosophy blog. And we're all in there working. I think it's great. I think it's such a nice feature.

KAPEHE: So, I have been at Sanity for 2.5 years and things still blow my mind. It's still magical and sparkly to me. When I do a tutorial, I always deploy, always look at the localized and side-by-side. I've never done local-to-local. So, this is like the coolest thing right now.

JASON: So, this is -- this is great. We have about 25 minutes left. And I would love to get some of this data on to the screen. So, I'm gonna really quickly create one more corgi. Chat, I need one more corgi name. Let me get over to Unsplash and kind a corgi. And let's see -- I need a -- oh, my god. What is this corgi's name?

KAPEHE: Look at that doggo, isn't that cute?

JASON: Too adorable. We have a very cute corgo pupper here. And Auxfuse named this dog Floof. And I agree. So, this is Floof. Let's see... where am I? Floof. Okay and we can do something like this is the cutest corgi puppy.

KAPEHE: I mean, that's true. That's the cutest corgi puppy I've ever seen.

JASON: Okay. Now we've got two corgi pups. We are now ready to display these on the site. And so, I'm back in my Next site. And I want to say -- I guess we could just put them both on one page. I don't think we're gonna have time to really style anything or go too wild here.

KAPEHE: So, we'll just edit straight into the app/page.tsx.

JASON: Okay.

KAPEHE: That is when you run it locally, it will just have the generic NUX stuff.

JASON: And if we look at this, because, again, we're running locally... I can -- it's out to the home page. localhost 3000. Did I make this too aggressive? Oh, no. Here we go. It's just -- I think -- this stuff is all still experimental. Like the app directory. So, this is still pretty slow. And I don't know if that's for the development mode or if it's because they still -- like the -- the app directory stuff I've seen with Next is still not super-performant. Like I've seen some demos that they just feel -- I feel like it's still getting there. Which is why this isn't production code. This is still beta.

KAPEHE: Yes.

JASON: Okay. So, I'm ready to edit this. So, I'm gonna just come in here and I think maybe dump everything?

KAPEHE: Everything. Everything in that return we don't need.

JASON: Okay. So, I'm just gonna get this -- and I think this will give us like some basic... so, that I think that should give us -- yeah. So, it's basic -- basic style so it's not just a plain page. And now I want to put our corgis in here. So --

KAPEHE: So, we'll need to do a couple of things. So, normally, you would have to have your client config probably in a different file so you can like use it throughout your app. But let's just put it directly into here. So, yeah, underneath that line.

JASON: Okay.

KAPEHE: Let's do const, client config. And that clientConfig is camel case. And equal that and open that project up. And we need projectId, dataset, and useCdn is false. And we did production --

JASON: Use Cdn, is it capitalized like that?

KAPEHE: Yes.

JASON: Okay. So, I know production... I'm gonna go copy the projectId out of here. Okay.

KAPEHE: Perfect. And then above we'll need to import that create client. Oh, wait. We haven't even used it yet. But we'll neat create client.

JASON: Is that from next Sanity or Sanity?

KAPEHE: That's from Next Sanity.

JASON: Okay. I'm ready to -- I'm making an assumption here, that I'm doing client equals create client?

KAPEHE: So, we're actually gonna do -- we're gonna create a function that will use a GROQ query to query for our contents. GROQ is a Sanity in-house made query language. You can use GraphQL with Sanity. But GROQ is the preferred way. But yeah. We'll use GROQ today. So, we'll do -- to get all the corgis. We'll do the function, get corgis. And then open that function up.

JASON: Okay.

KAPEHE: And then do a return from that. And then we'll do create client. Oh, I guess you did client. So, you could do client.fetch.

JASON: I can get rid of this. We'll do a create client and then I'm gonna pass in the client config. And then we're doing a dot fetch?

KAPEHE: Yep.

JASON: Okay.

KAPEHE: And then open up that and GROQ -- we need to import GROQ -- GROQ is spelled --

JASON: I let autocomplete do it so we have it now. It's a tag template literal, right?

KAPEHE: The way GROQ is done is to get everything you want an asterisk. We'll do an asterisk. And square brackets is filtering down your query. We could get all right now. But we want to filter down to exactly what we want. We'll do square brackets and then underscore type is equal to, and it's double equal, and then in quotes, corgi. Because that was our type.

JASON: So, that's all of our corgis. Okay.

KAPEHE: I don't know if you need spaces around the equal signs.

JASON: For safety, we won't. Or we will. Okay. Is & is this -- is this -- like are we looking at -- is this async? are we --

KAPEHE: So, we will -- when we start calling this, we will change the export default function home. That will be async await. But right now, this is just calling to get our content.

JASON: Okay. So, we're gonna open up one of these.

KAPEHE: Yeah. And I would -- I would let them touch. I would let the square and the curly -- I actually don't know if they can --

JASON: Let them be friends. Okay. I gotcha.

KAPEHE: Okay here. And filter down to type corgi. Wasn't the type document, someone asked? You are correct, the parent was document. But we have a specific one that we want to pull out. So, we are pulling out the type corgi. I don't know if you want to go back to that code. But it was --

JASON: So, this is kind of the interesting piece about this. We're getting different types. And when you have a document-level type, you can have multiples of these. So, if you search for document, I think you can just do a query that would load all documents. And that would be like asterisk, square brackets nothing in it. And that will give you all documents in the content lake. But if we want to filter down to a certain type of document, that will be the name signifier.

KAPEHE: Because we want the specific corgi document. You're right, we could get a bunch. In this case, we have just one so it won't do much.

JASON: We don't have time to do it today. But if you haven't tried it, use the Sanity Vision plugin. I will -- I'll send a link to it to the chat. But yeah. You should give this a shot because this is gonna help a lot. I have -- I have given the Sanity team a lot of crap over the years about inventing their own query language. Because I, you know, it's such a programmer thing to like invent your own everything. But against -- against my own will, I have had to admit that GROQ is actually excellent. And I'm sure Knut is stoked that I'm saying that out loud right now.

KAPEHE: Yeah. We're all stoked. Yeah, I'm a big fan of GROQ. Once you start using it, it just -- and it's -- yeah. It's just really great. I have a bunch of GROQ in 2 videos. Where I go through real quick how to do a query with a certain function. But yeah. It's good.

JASON: Yeah, that's actually -- where would I find those if I want to send somebody to that?

KAPEHE: So, the Sanity YouTube has all of those. Yeah, Sanity.io, YouTube.

JASON: Okay. Let's do here. All right. So, I'm just gonna link directly to this and y'all can go find those videos from Kap.

KAPEHE: Welcome to Sanity. io's -- there's me.

JASON: So, I've made a query and now we can -- we're gonna put in fields, right?

KAPEHE: Yeah. We can bring out exactly what we want. So, we could do IDs, we could do names, we could do the slug. Now, some of them need to be written a specific way. Oh, and we need commas between each one. So, name, slug.

JASON: We need commas. And so, I want the slug and then we want that image.

KAPEHE: So, slug --

JASON: And we want the content. And I imagine I'm gonna need some special stuff to make these work.

KAPEHE: Yes. But as this worked, this is what you expect. With slug and image we need to do a little bit different. With slug, put quotes around it, and then slug.current. Because slugs can get messy. This is make sure that whatever slug we're looking at, it's the current slug. And then with image --

JASON: This is like in GROQ. We're basically aliasing slug.current. So, instead of getting like an object back that's slug and then there's subfields and current and dot -- I don't know what the other ones are, but I imagine it keeps a version history or something. Where we are saying, throw away everything else in this object. Just give me back the current slug, right?

KAPEHE: Yes. You're renaming it. You're saying that slug.current now when I type it out, it's just slug.

JASON: Got it. Okay. And then for image?

KAPEHE: The same thing for image. We'll do quotes around image. And then colon and then image.asset. And then an arrow URL. And I will explain this.

JASON: Okay.

KAPEHE: So, if grow back real quick to the Studio at the admin. And you click into one of these beautiful corgis. And -- do the three dots.

JASON: Okay I want to see more of Floof. Here we go. Here's Floof.

KAPEHE: Nice. Do the three dots at the top. And then inspect.

JASON: Inspect. Okay. We've got --

KAPEHE: Now, here. Find the image one.

JASON: Here's the image. So, we've got the asset.

KAPEHE: Yeah. So, we are pulling out -- so, see how there's a reference to that image. So, if we were to de-reference this in that would be a whole bunch of information about our image. We're not gonna de-reference it right now. But that arrow that we did is de-referencing it for us and pulling out just the URL because that's all we want. So --

JASON: Got it.

KAPEHE: That is what we did here --

JASON: And then if I can intuit this correctly, I can also do this to get my alt.

KAPEHE: Yeah.

JASON: Great. Okay. And then do I need to do anything special with content since that's gonna be portable text?

KAPEHE: No. I don't think so.

JASON: Okay. So, I have my get corgis. And then down here, do I just call that? Or how -- how would one pull it?

KAPEHE: Yeah. So, in there, we're gonna do -- so, we're gonna change that to an async. That default async function.

JASON: Okay.

KAPEHE: And underneath this, const corgis equal to await, get corgis. Now we're getting that GROQ queries content that it's querying for.

JASON: Okay. I can just dump it to make sure that it's working. We'll do one of these like JSON.stringify. We'll do corgis. Null. 2 and... that should -- if I go back to my -- I guess we'll only go back here. Here. Look at it. Look at the data!

KAPEHE: So much data! But yeah.

JASON: And this is exactly what we wanted. here's our alt. Here's our image, here's our name, here's our slug. And we can see that like this image did resolve to just a URL and not just an objective image data. And the alt went into the image and got the alt tag out. And this is where I think -- this is what won me over on GROQ. Is this ability shape your data in the query itself instead of making a query and then writing a function to like rearrange the data into the shape you want. This is pretty excellent, right? Like I think this is the sort of thing that, you know, if you're gonna reinvent the wheel and make your own query language, you do it for stuff like this because you can't do this with GraphQL or REST. It always takes extra JavaScript at the end to kind of write middleware. So, the middleware goes away with GROQ. And I think that is the big selling point for it.

KAPEHE: Yeah. So, I mean, we probably don't want to just look at a bunch of JSON.

JASON: Probably not. Probably not.

KAPEHE: But yes, GROQ makes it really easy to like -- so, if you had more stuff or trying to get really dynamic with this app, you would take that function, that get corgis function that we made and you would put it into a different file and call it Sanity utils and have all your GROQ queries in there and call them. You can organize it that way. In this case, we're putting it right into the file. So, yeah.

JASON: Okay. I'm just gonna give this like some -- I'm not going to style this. We're just gonna kind of dump data because we're gonna run out of time if I try to write CSS. But I have a couple things that I know we can do right out of the gate. So, I can do an H2. And I'm gonna use the corgi.name. Because looking at my data here, I can see I've got an array. Each one of these is a corgi. And I've got a .name in there. I can do corgi.name. What are you mad about? Are you mad that I didn't type it. I didn't type it. Okay. So, that's fine. I'm not going to type it.

KAPEHE: That's okay. Yeah.

JASON: Because we'll get there, we'll get there. So, we're gonna do a source. And that's going to use the corgi.image. And then we want the alt. And that's going to be our corgi.alt. And for the content, can I just do like corgi.content? My gut says this isn't gonna work. But I'm gonna try it and we're gonna see what happens. Yelling at me, TypeScript. Boo! What is this? Objects are not valid...

KAPEHE: So... let's see.

JASON: What?

KAPEHE: Corgi --

JASON: What have I done, chat? Why doesn't it like this?

KAPEHE: Return... an ID?

JASON: Yeah. What are you mad about? You're saying... oh, missing key prop. You are correct! Oh, I'm in -- I'm not writing Solid anymore. Okay.

KAPEHE: We could also bring in the ID into the GROQ query. So, you could do key is equal to corgi._ID and then bring in _ID. So, you actually have that specific ID.

JASON: Okay. So, now that will get us in less trouble here. It is mad at me about -- objects are not valid --

KAPEHE: So, if we want, we can use the image from Next. The Next image stuff. That might be --

JASON: We can use the image... okay. Yeah. Let's see... there's Next image. We'll use Next image.

KAPEHE: Yeah. So, do image. Source corgi.image, alt, corgi.alt. Corgi dot -- okay. And then --

JASON: I think it might be this that it's unhappy about. Because I think that is our object.

KAPEHE: Okay. There is one more fix we need to do.

JASON: Image was source? Missing there with property --

KAPEHE: So, this is a Next 13 thing. You needed to image handling in the next.config.js file. And you need to -- yeah.

JASON: All right.

KAPEHE: So, in here. Underneath that first experimental -- yeah. Right underneath that. Type in "Images" and then colon. Open up a curly. And then remote patterns, camel case. This is Next. And this is just saying, like, oh, it's valid. It's cool. Open up an array, and then open up an object. And then in here, protocol: And the HTTPS in quotes. And then comma. And then underneath that, host name. All lower case. Colon. And then in quotes, CDN.sanity.io.

JASON: Okay.

KAPEHE: And then underneath that, port, colon, and then an empty string. And that should -- that should make it work. So, this is -- this is image handling for Next.

JASON: Is it gonna yell at us about the width still?

KAPEHE: And then yeah, width and height might be the final thing.

JASON: I'm just gonna hard code a width of like -- because I don't want this to blow out the screen. We'll just say the width is gonna be -- we'll call it 300 because that should be good enough. And then that will give us... what? Missing required height property? Boo! Okay.

KAPEHE: Just do 300.

JASON: Oh, we're gonna squish these poor little corgis.

KAPEHE: That's okay.

JASON: This is... image host name, CDN.sanity.io. Do I have to restart the server now that we've added this?

KAPEHE: Yes.

JASON: Okay. I can do that. So, we're going to restart. Quit helping. There we go. Running. Come out here. Do a reload. And... now we have... okay. Our -- oh, we squished Floof.

KAPEHE: Floof! And Beatrice looks a little taller.

JASON: Yeah. Beatrice is -- Beatrice is getting helped by the camera. Floof it looking real gremlin-y. All right. So, this is -- that's something that we can fix because we would get in the admin we would be able to pull out like the asset details because we have the image in Sanity. Unfortunately, we are not gonna have time to dig into that specific thing. And I think we might be able to squeeze the portable text under the wire here, maybe?

KAPEHE: Yeah, let's -- it should be dot content list, see what happens.

JASON: So, the dot content is an object. If I try to put this in, it's yelling at me. We need to convert it back to HTML.

KAPEHE: That's right. We need to import portable text block from Sanity.

JASON: Okay.

KAPEHE: At the top of it --

JASON: Okay. Import, the curly brace portableTextBlock, from Sanity. Thank you, autocomplete.

KAPEHE: And wherever you want to put that, use portable text, and then the value is equal to corgi.content. Wait, no. It's portable text. That's my bad. Portable text from -- oh, gosh. There's -- there's a little bit that needs to happen here.

JASON: portable text from?

KAPEHE: It's not from Sanity. It's from @portable-text/react.

JASON: I assume I'm gonna need to install.

KAPEHE: Yeah.

JASON: Okay. Do that. So, I'm going to stop here, npm install portable-text React. Nope. What did I do? Is there no hyphen?

KAPEHE: Do -- take out the react part and just do @portable-text.

JASON: Oh. Right. That would make sense. And it probably not -- oops. Like that?

KAPEHE: Yeah.

JASON: Portable-text. Am I spelling this wrong?

KAPEHE: Portable... text. Okay. Yeah. It's @portable-text/react, no hyphen. Thank you, chat,

JASON: I can do this. Thank you, chat! Okay. Here we go. So, we're doing this. I'm coming up here, getting rid of that. We got this. We're gonna npm run Dev again. And we are gonna get this running under the wire. We've got 2 minutes. Okay. So, this is now functioning. No errors. It's not yelling at me. We got to get our type. But that's okay. We can live without the type for today. Is this Next being slow or is there actually a problem? Hey! Look at it go! There is our -- here's our text coming in. And it's -- it's all loading the way that we want. We didn't style anything. So, this is just kind of inheriting whatever the default styles were from create next app. So, here we are loading some slightly squished corgis. But we did all that in a really short period of time. And with a little bit more work, digging into the Sanity docs, we would be able to go in and get all of the details. So, like if we looked at the -- the image docs here we would be able to figure out how to get all of those pieces. So, this -- I mean, this is -- this is great. This is really powerful stuff. And now that we're out of time, Kap, where should people go if they want to keep going down this rabbit hole and get better at building things with Sanity?

KAPEHE: Yep. When you go to that YouTube for Sanity, there's that crash course that you'll see right at the beginning. That is a really great getting started with v3 crash course. But if you want to join the Sanity Community, Slack.sanity.io. There are so many like awesome community members and the whole Sanity team is in there. But if you have any questions, like as you go, definitely ask everybody, Slack.sanity.io. And then we're just creating content all the time. Especially with v3 coming out. We're trying to like -- like docs have been updated -- like 100 different doc pages have been updated to accommodate for this v3 launch. So, docs are being updated. The new Next Sanity is getting updated. We're finding things once in a wile that need to be fixed. But yeah. The content is coming. I'm creating a full tutorial of Next and Sanity, beginning to end of personal website. That's coming. But yeah. If you have specific questions, the best place to find all of us is that Slack Sanity group.

JASON: Excellent. All right. So, with that, we're gonna call this one a success. This was -- this was killer. I mean, we were able to get --

KAPEHE: Yeah.

JASON: So much done. The studio looks cool. I love dark mode now, I love that you can embed it right in your website. If you want to keep up with updates from Kap, you can head over to Twitter. And follow there. Also, this episode, like every episode, has been live captioned. We've had Amanda here from White Coat Captioning here all day. Thank you so much, Amanda, and that is made only to through the support of you are sponsors, Netlify, Nx, New Relic, Pluralsight, all kicking in to make this show more access to believe more people, which I very much appreciate. While you're checking things out on the site, check out the schedule. We have an absolute banger of a schedule. We will be back on Tuesday with a solo stream. And then do some visual Editing with Next.js and contentful. If you haven't seen that over the last few years, definitely tune in for this. The week of the 20th, something special, observability week with New Relic. Four straight streams Monday through Thursday, covering a bunch of amazing stuff. I have the Solid seam, how to share an Astro site between multiple frameworks. Follow on Twitch. Set the notifications so you know when we go live. Subscribe on YouTube, all the things that you know when new content is happening. Don't miss any of these. They are going to be incredible. Kap, thank you so much for spending time with us today.

KAPEHE: Thanks for having me on. This was really Great. We finished it.

JASON: We did it! This is great. Chat. as always, thanks for hanging out. We're gonna go raid Martine Dowden. Thanks, y'all.